Is it possible to checkpoint goroutine?

blov · · 1881 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p>I know that goroutine can perform some computations like following</p> <pre><code>func say(msg string) { for i := 0; i &lt; 3; i++ { runtime.Gosched() time.Sleep(1000 * time.Millisecond) fmt.Println(msg, &#34; i: &#34;, i) } } func main() { go say(&#34;world&#34;) say(&#34;hello&#34;) } </code></pre> <p>Then I am wondering is it possible to capture goroutine&#39;s state and save it e.g. bytes array for later use? </p> <p>Any suggestions or advice? Thanks</p> <hr/>**评论:**<br/><br/>TheMerovius: <pre><p>No, it is not possible <em>in general</em>. You would need to build your checkpoint-facilities yourself and customarily for the state your goroutine could hold. <a href="http://play.golang.org/p/BZ53SJiiM5" rel="nofollow">http://play.golang.org/p/BZ53SJiiM5</a> gives a rough example.</p> <p>But I don&#39;t know if this is really as usefull as you imagine it to be.</p> <p>[edit] <a href="http://play.golang.org/p/8rzgXRS_ek" rel="nofollow">http://play.golang.org/p/8rzgXRS_ek</a> also restores</p></pre>tjackson1441: <pre><p>@TheMerovius That looks similar to panic(), recover() mechanism. And that would require users manually decide what to save. </p> <p>@garoththorp In this scenario users have to periodically emit corresponded state/ information so that later on it can be restored accordingly.</p> <p>Thanks for all your help. It&#39;s very useful, I appreciate it! </p></pre>LimEJET: <pre><p>There is a &#34;reply&#34; button under each post. Also, highlighting people is done using <a href="/u/username" rel="nofollow">/u/username</a>. It&#39;ll turn into a link and they will be notified.</p> <p>As for the answer, there is no real use for saving an entire goroutine. You can just store the data it handles and return, then spin up another goroutine with that data when you need it again. Goroutines are not expensive, so you&#39;ll incur no real overhead from doing that.</p> <p>I guess the important question is, <strong>what is it that you want to accomplish?</strong></p></pre>tjackson1441: <pre><p>Thanks for the reply. I am thinking to let users supply functions and delegate those functions to the server for executing long running tasks. So it would be nice if the server can capture goroutine&#39;s state/ stack; then later on the system can continuously work on where it was left off. </p></pre>LimEJET: <pre><p>That just sounds like time sharing. It sounds like you want an operating system instead of a programming language. </p> <p>Allowing users to supply their own source code is not only dangerous, it&#39;d also be pretty damn hard considering Go is compiled and statically linked.</p></pre>gngl: <pre><blockquote> <p>It sounds like you want an operating system instead of a programming language. </p> </blockquote> <p>Which could be strangely appropriate since Go partly originates from Oberon in spirit. ;)</p></pre>LimEJET: <pre><p>And Plan 9 (which actually does timesharing; Oberon does not) even more so.</p></pre>tjackson1441: <pre><p>Original I thought that golang would have provided some mechanism like panic, recover, and underlying having gorutine stack growable, etc. so it looks like possible to simply walk in that direction. But you are right that it&#39;s not compiled into something like byte code which makes it hard to transferred once across the network. I just found the issue - <a href="https://github.com/golang/go/issues/5514" rel="nofollow">https://github.com/golang/go/issues/5514</a></p> <p>Thanks for the advice! </p></pre>jerf: <pre><pre><code>type Computation interface { Begin() Suspend() interface{} // this is really a class method: Resume(interface{}) Computation } </code></pre> <p>This is about the best you can do. The user can supply an object that conforms to this interface. It is the user&#39;s responsibility to arrange for checking for the Suspend call every so often. It is the user&#39;s responsibility to ensure that the returned value from Suspend is indeed sufficient to resume the calculation. You need to specify how the value coming from Suspend will be serialized or stored (i.e., &#34;must be round-trippable via encoding/json&#34; or something). A distinguished value should probably be emitted from Suspend if the Computation is complete. (Adding a <code>Name() string</code> to the interface can be helpful as you can then use that to register the values.)</p> <p><code>Resume</code> is actually a class method; as long as you have an object of the correct type, even the zero-value, calling Resume yields a new Computation that you can then call Begin on, and suspend later as needed. If you need some more solid notification of completion you may want to make <code>Begin(func())</code>, where you pass in a function to be called upon completion that does whatever you need it to do.</p> <p>This is all you can do. There&#39;s no mechanism for suspending and moving goroutines themselves. There&#39;s no mechanism for sending interrupts to a goroutine... it has to be actively listening. The type system is not capable of enforcing any of the constraints on the user&#39;s code that I mentioned; that would take Haskell&#39;s type system at a rough minimum.</p> <p>Oh, and you&#39;ll have to actually compile and/or recompile an executable for each new program. This could be anything from &#34;really annoying&#34; to &#34;total stopper&#34; depending on your situation.</p> <p>You may want to consider writing or using an interpreter for your long-running task, but if it&#39;s a long-running task that is also performance sensitive this won&#39;t help the performance any.</p> <p>If you can give more details about the nature of the long-running tasks we may be able to advise on a better language, or a better approach. Please also specify whether you trust your users, and think <em>hard</em> about that statement before you&#39;re too quick on the draw.</p></pre>tjackson1441: <pre><p>The code is simply for internal use like sandbox so security is not the most important issue (of course security is very important when considering for the entire environment). </p> <p>I agree I need to rethink about that for more detail because it&#39;s apparently not what I original thought (capture the state, dump it, etc.). Big Thanks! </p></pre>TheMerovius: <pre><p>I am unsure whether this is a good idea or not, but <em>if</em> you really want to do that, here&#39;s (roughly) what you <em>should</em> do:</p> <ul> <li>Have them write their program as a main-package</li> <li>Check for inclusion of unsafe, compile the main-package with go-nacl</li> <li>Run that program in a separate process [edit] with seccomp enabled, I think go-nacl implies that, but am unsure [/edit]</li> <li>To suspend, SIGSTOP, dump it&#39;s core, safe it to disk/transfer it</li> <li>To resume, restore it&#39;s core, SIGCONT it.</li> <li>All the while, make sure that you <em>never</em> restore a process image to a different binary it was created from (so, transfer the compiled binary with the core)</li> </ul> <p>This is more or less, what the playground is doing, or the Google App Engine (probably). It is an <em>absolutely crazy</em> idea to have users function run in a separate goroutine in the same memory space as a) the supervisor and b) other users code. <em>batshit, absolutely unforgivable crazy</em> (I really want this message to come across, so I don&#39;t want to understate it).</p></pre>gngl: <pre><blockquote> <p>It is an absolutely crazy idea to have users function run in a separate goroutine in the same memory space as a) the supervisor and b) other users code. </p> </blockquote> <p>It&#39;s not really all that crazy, it&#39;s just that Go might not have the necessary mechanisms to implement it properly - you&#39;d need hard resource control to reliably cancel computations diverging in both time and space (and time might actually be somewhat easier to control for than space). The runtime would also need to feature functions for module loading and unloading, something the current Go runtime also doesn&#39;t support (and maybe never will?). You&#39;d probably need a more Oberon-like runtime for this to work.</p></pre>TheMerovius: <pre><blockquote> <p>It&#39;s not really all that crazy, it&#39;s just that Go might not have the necessary mechanisms to implement it properly</p> </blockquote> <p>Yes, I was referring to go :) It&#39;s not a huge problem in e.g. python.</p></pre>tjackson1441: <pre><p>I really need to rethink about this. Really appreciate your suggestions. </p></pre>gngl: <pre><p>Just for the record, what you&#39;re describing is generally called &#34;mobile code&#34; in CS. But there&#39;s only a few systems that can do this in a fully general way, such as Gambit/Termite.</p></pre>TheMerovius: <pre><blockquote> <p>That looks similar to panic(), recover() mechanism.</p> </blockquote> <p>I don&#39;t know, what you mean by that.</p> <blockquote> <p>And that would require users manually decide what to save.</p> </blockquote> <p>Yes, that&#39;s exactly what I meant, when I said, there is no general way and that you need to build that customarily for the state your goroutine could hold.</p> <p>Doing something like this (in general) would fundamentally undermine memory safety. Ain&#39;t going to happen ever and is a very bad idea from so many points of views.</p></pre>garoththorp: <pre><p>Look into channels. You can use them to pass data between goroutines. For example, you can have those goroutines stream strings to the main goroutines, and so stuff with them there.</p></pre>

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1881 次点击  
加入收藏 微博
2 回复  |  直到
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传