Follow-up thoughts on making Go unusable

polaris · · 410 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p>This problem has really captured my fancy. <a href="https://www.reddit.com/r/golang/comments/4klmwe/code_challenge_can_go_be_rendered_unusable/" rel="nofollow">Previous post.</a></p> <p>Here&#39;s the full dialog so far. I repeat much of what was said in that post because I&#39;m trying to gather my thoughts.</p> <p>The goal is to write some code in Go such that, for arbitrary user code confined to a certain scope of it, Go does not satisfy all of the following criteria for something to be considered a programming language:</p> <ul> <li>It supports some representation of positive integers. <ul> <li>Impossible. While we can erase the names of the built-in integer types by shadowing them, <code>:=</code> lets the user freely initialize integers.</li> </ul></li> <li>It supports some representation of lists or tuples. <ul> <li>Impossible due to list and string literals.</li> </ul></li> <li>It can determine the sum of two positive integers: either by adding them together, or taking in a tuple of three integers and outputting a boolean indicating whether one is the sum of the other two. <ul> <li>Impossible due to the built-in &#34;+&#34; operator.</li> </ul></li> <li>It can determine whether a positive integer is prime. <ul> <li>Again impossible.</li> </ul></li> <li>The result of the above two computations can affect the program&#39;s output.</li> </ul> <p>This last criterion appears to be the only one we can destroy.</p> <p>The obvious solution is to confine the user&#39;s code to the end of <code>main</code>, and shadow the built-in functions <code>panic</code>, <code>print</code>, and <code>println</code> as constants. Without the ability to import anything, the user fights back: they can panic by improperly indexing an array, say:</p> <pre><code>panicker := []interface{}{} _ = panicker[1] </code></pre> <p>We can counteract this easily by calling recover to absorb panics, so our program now looks like this:</p> <pre><code>package main func main() { defer func() { recover() }() const ( panic = iota print println ) // User code here } </code></pre> <p>If Go were a lesser language, we might declare victory here. But this only absorbs panics in the <code>main</code> goroutine. Thanks to Go&#39;s concurrency features the user can simply create new goroutines and panic in them! The fact that all goroutines terminate when <code>main</code> does won&#39;t help, because the user can block the goroutine they&#39;re using with <code>select {}</code> and allow others to execute.</p> <p>At this point, I see two possible paths:</p> <ul> <li>Prevent the user from accessing any possible means of output.</li> </ul> <p>We can <code>import . os</code>; call <code>Close()</code> on <code>Stdin</code>, <code>Stdout</code>, and <code>Stderr</code>; and then shadow everything else in the package as constants. This is almost what we want, as even panics don&#39;t print anything. But the user has one last bit of IO that we can&#39;t control: the process&#39;s exit code. A Go program terminated by a panic has exit status 2, which is even printed if you use <code>go run</code>. With this the user can add and detect primes by the decisional model.</p> <ul> <li>Prevent any code in user-created goroutines from executing.</li> </ul> <p>This appears to be <em>just</em> shy of possible. My first thought was</p> <pre><code>import . &#34;runtime&#34; GOMAXPROCS(1) LockOSThread() </code></pre> <p>But <code>GOMAXPROCS</code> limits only the number of <em>parallel</em> goroutines, not the number of runnable goroutines (<a href="http://stackoverflow.com/questions/37426511/why-doesnt-gos-lockosthread-lock-this-os-thread" rel="nofollow">stack overflow</a>. My next thought was to limit the OS threads usable by the program with</p> <pre><code>import . &#34;runtime/debug&#34; SetMaxThreads(...) </code></pre> <p>I&#39;m sure these results will vary from system to system. On my system, 4 or fewer as the argument to <code>SetMaxThreads</code> instantly crashes the program (and we must actually execute the user&#39;s code), and 5 or greater appears to have no effect. Perhaps a Go concurrency whiz can help me in this respect.</p> <p>As a branch-off from the above idea:</p> <ul> <li>Create another goroutine that is constantly communicating back and forth with <code>main</code>, where the user&#39;s code lives. If <code>main</code>&#39;s communications cease, because it has been blocked that a user-created goroutine might execute, the other goroutine kills the program.</li> </ul> <p>Again, <em>just</em> shy of possible. How can the helper tell that <code>main</code>&#39;s communications have ceased? Goroutines have no identity. A little bit of brainstorming led to this odd code:</p> <pre><code>c := make(chan bool, 2) c &lt;- true c &lt;- true go func() { for { &lt;-c if len(c) == 0 { os.Exit(0) } } }() for { c &lt;- true // User code here } </code></pre> <p>This prevents the user from blocking <code>main</code>, but by wrapping the code in a loop, we prevent <code>main</code> from destroying user goroutines that would be destroyed if the user <em>didn&#39;t</em> block main. Is it one or the other, or does this idea have merit?</p> <p>Thanks for reading. I can&#39;t wait to hear your suggestions.</p> <hr/>**评论:**<br/><br/>TheMerovius: <pre><p>How would this be forbidden by the rules?</p> <pre><code>runtime.GOMAXPROCS(1) go func() { for {} }() </code></pre> <p>If I&#39;m not mistaken that should starve the main goroutine, i.e. prevent any computation to take place. At least in gc?</p></pre>Partageons: <pre><p>First, <a href="https://play.golang.org/p/xYWd3jAlhn" rel="nofollow">it doesn&#39;t work</a>. Second, even if it did work, then the user&#39;s code will not be executed, which is a sub-requirement of the challenge as stated later on. If things like that were allowed, I would have stopped at <code>SetMaxThreads(4)</code>, which instantly crashes the program.</p></pre>twanies: <pre><p>Plz solve real life problems with Go.</p></pre>dlsniper: <pre><p>What&#39;s the point of this? Who would ever need this? Why? How can this be meaningful in any way? Call me shortsighted but I fail to see why should one make this effort?</p></pre>barsonme: <pre><p>fun of it. same reason why people code golf.</p></pre>

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

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