My daemon-ish program panics, how can I get at the message?

polaris · · 138 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p>In normal terminal / CLI programs this is easy, the panic message is printed just as the program dies.</p> <p>But what I have is a dead-simple json-rpc-ipc-via-pipes (no need for sockets here) concoction, the client being a nodejs app and my Go program acting as the clients &#34;server&#34;. They communicate brilliantly simply via writeln/readln ping-pong communication. (Neat because I can talk to the tool via terminal just like the client app would if needed to investigate the odd bug.)</p> <p>Nonetheless some async background activity (goroutines, waitgroups, some mutexes) has by now made it into the go program and so it occasionally crashes and I&#39;m wondering how I can speed up my investigations here. This is regrettably not reproducable via terminal even when the exact same sequence of commands is sent manually as the client did to provoke the die-off --- so sth. timing-related and most likely goroutine-related.</p> <p>Is the panic msg always printed to stderr? If I redirect stderr to a local file, will it allow flushing before proceeding to die? Can some custom logger be hooked up to Go&#39;s built-in &#34;print panic message&#34; logic? If I could just <em>see</em> the message that&#39;d be 80% of the battle.</p> <p>(If that message is just sent to stdout I can already report it never makes it in time to my client or in any event node closes that pipe/ipc reader before allowing a final <code>line</code> event.)</p> <hr/>**评论:**<br/><br/>Ballresin: <pre><p>I ran into a similar problem. Found I was often running into Index Out Of Range or nil pointers. Frustrating when the program dies silently.</p> <p>I use this to grab a stack trace:</p> <pre><code>func Stack() []byte { buf := make([]byte, 1024) for { n := runtime.Stack(buf, false) if n &lt; len(buf) { return buf[:n] } buf = make([]byte, 2*len(buf)) } } </code></pre> <p>And inside any top-level function or goroutine I suspect might panic, I recover and perform the dump:</p> <pre><code>defer func() { if err := recover(); err != nil { log.Print(fmt.Sprintf(&#34;Recovering panic in myInfinityFunc(): %v&#34;, err)) log.Print(string(Stack())) sendLogsToServer() time.Sleep(3 * time.Second) myInfinityFunc() } }() </code></pre> <p>Though if anyone has more brilliant approaches to this I&#39;m all ears too.</p> <p>In my case it will echo to the logs, to the console if running interactive, as well as upload the logs to the server for investigation. I then kick the function off again after a short nap to help mitigate possible flapping.</p></pre>ZetaHunter: <pre><p>consider adding some recovery to catch the panic and print the error</p> <p>also you should probably try your own ideas before coming for suggestions, that said, try logging stderr to a file as well.</p></pre>

入群交流(和以上内容无关):Go中文网 QQ 交流群:798786647 或加微信入微信群:274768166 备注:入群;关注公众号:Go语言中文网

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