How to use LogTrace method of td Package

Best Go-testdeep code snippet using td.LogTrace

proc_linux.go

Source:proc_linux.go Github

copy

Full Screen

1<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"2 "http://www.w3.org/TR/html4/transitional.dtd">3<html>4<head>5 <meta http-equiv="content-type" content="text/html; charset=utf-8">6 <title>Source file /src/pkg/debug/proc/proc_linux.go</title>7 <link rel="stylesheet" type="text/css" href="../../../../doc/style.css">8 <script type="text/javascript" src="../../../../doc/godocs.js"></script>9</head>10<body>11 <script>12 // Catch 'enter' key down events and trigger the search form submission.13 function codesearchKeyDown(event) {14 if (event.which == 13) {15 var form = document.getElementById('codesearch');16 var query = document.getElementById('codesearchQuery');17 form.q.value = "lang:go package:go.googlecode.com " + query.value;18 document.getElementById('codesearch').submit();19} return true;20}21 // Capture the submission event and construct the query parameter.22 function codeSearchSubmit() {23 var query = document.getElementById('codesearchQuery');24 var form = document.getElementById('codesearch');25 form.q.value = "lang:go package:go.googlecode.com " + query.value;26 return true;27} </script>28<div id="topnav">29 <table summary="">30 <tr>31 <td id="headerImage">32 <a href="../../../../index.html"><img src="../../../../doc/logo-153x55.png" height="55" width="153" alt="Go Home Page" style="border:0" /></a>33 </td>34 <td>35 <div id="headerDocSetTitle">The Go Programming Language</div>36 </td>37 <td>38 <!-- <table>39 <tr>40 <td>41 <! The input box is outside of the form because we want to add42 a couple of restricts to the query before submitting. If we just43 add the restricts to the text box before submitting, then they44 appear in the box when the user presses 'back'. Thus we use a45 hidden field in the form. However, there's no way to stop the46 non-hidden text box from also submitting a value unless we move47 it outside of the form48 <input type="search" id="codesearchQuery" value="" size="30" onkeydown="return codesearchKeyDown(event);"/>49 <form method="GET" action="http://www.google.com/codesearch" id="codesearch" class="search" onsubmit="return codeSearchSubmit();" style="display:inline;">50 <input type="hidden" name="q" value=""/>51 <input type="submit" value="Code search" />52 <span style="color: red">(TODO: remove for now?)</span>53 </form>54 </td>55 </tr>56 <tr>57 <td>58 <span style="color: gray;">(e.g. &ldquo;pem&rdquo; or &ldquo;xml&rdquo;)</span>59 </td>60 </tr>61 </table> -->62 </td>63 </tr>64 </table>65</div>66<div id="linkList">67 <ul>68 <li class="navhead"><a href="../../../../index.html">Home</a></li>69 <li class="blank">&nbsp;</li>70 <li class="navhead">Documents</li>71 <li><a href="../../../../doc/go_tutorial.html">Tutorial</a></li>72 <li><a href="../../../../doc/effective_go.html">Effective Go</a></li>73 <li><a href="../../../../doc/go_faq.html">FAQ</a></li>74 <li><a href="../../../../doc/go_lang_faq.html">Language Design FAQ</a></li>75 <li><a href="http://www.youtube.com/watch?v=rKnDgT73v8s">Tech talk (1 hour)</a> (<a href="../../../../doc/go_talk-20091030.pdf">PDF</a>)</li>76 <li><a href="../../../../doc/go_spec.html">Language Specification</a></li>77 <li><a href="../../../../doc/go_mem.html">Memory Model</a></li>78 <li><a href="../../../../doc/go_for_cpp_programmers.html">Go for C++ Programmers</a></li>79 <li class="blank">&nbsp;</li>80 <li class="navhead">How To</li>81 <li><a href="../../../../doc/install.html">Install Go</a></li>82 <li><a href="../../../../doc/contribute.html">Contribute code</a></li>83 <li class="blank">&nbsp;</li>84 <li class="navhead">Programming</li>85 <li><a href="../../../../cmd/index.html">Command documentation</a></li>86 <li><a href="../../../../pkg/index.html">Package documentation</a></li>87 <li><a href="../../../index.html">Source files</a></li>88 <li class="blank">&nbsp;</li>89 <li class="navhead">Help</li>90 <li>#go-nuts on irc.freenode.net</li>91 <li><a href="http://groups.google.com/group/golang-nuts">Go Nuts mailing list</a></li>92 <li><a href="http://code.google.com/p/go/issues/list">Issue tracker</a></li>93 <li class="blank">&nbsp;</li>94 <li class="navhead">Go code search</li>95 <form method="GET" action="http://golang.org/search" class="search">96 <input type="search" name="q" value="" size="25" style="width:80%; max-width:200px" />97 <input type="submit" value="Go" />98 </form>99 <li class="blank">&nbsp;</li>100 <li class="navhead">Last update</li>101 <li>Thu Nov 12 15:49:05 PST 2009</li>102 </ul>103</div>104<div id="content">105 <h1 id="generatedHeader">Source file /src/pkg/debug/proc/proc_linux.go</h1>106 <!-- The Table of Contents is automatically inserted in this <div>.107 Do not delete this <div>. -->108 <div id="nav"></div>109 <!-- Content is HTML-escaped elsewhere -->110 <pre>111<a id="L1"></a><span class="comment">// Copyright 2009 The Go Authors. All rights reserved.</span>112<a id="L2"></a><span class="comment">// Use of this source code is governed by a BSD-style</span>113<a id="L3"></a><span class="comment">// license that can be found in the LICENSE file.</span>114<a id="L5"></a>package proc115<a id="L7"></a><span class="comment">// TODO(rsc): Imports here after to be in proc.go too in order</span>116<a id="L8"></a><span class="comment">// for deps.bash to get the right answer.</span>117<a id="L9"></a>import (118 <a id="L10"></a>&#34;container/vector&#34;;119 <a id="L11"></a>&#34;fmt&#34;;120 <a id="L12"></a>&#34;io&#34;;121 <a id="L13"></a>&#34;os&#34;;122 <a id="L14"></a>&#34;runtime&#34;;123 <a id="L15"></a>&#34;strconv&#34;;124 <a id="L16"></a>&#34;strings&#34;;125 <a id="L17"></a>&#34;sync&#34;;126 <a id="L18"></a>&#34;syscall&#34;;127<a id="L19"></a>)128<a id="L21"></a><span class="comment">// This is an implementation of the process tracing interface using</span>129<a id="L22"></a><span class="comment">// Linux&#39;s ptrace(2) interface. The implementation is multi-threaded.</span>130<a id="L23"></a><span class="comment">// Each attached process has an associated monitor thread, and each</span>131<a id="L24"></a><span class="comment">// running attached thread has an associated &#34;wait&#34; thread. The wait</span>132<a id="L25"></a><span class="comment">// thread calls wait4 on the thread&#39;s TID and reports any wait events</span>133<a id="L26"></a><span class="comment">// or errors via &#34;debug events&#34;. The monitor thread consumes these</span>134<a id="L27"></a><span class="comment">// wait events and updates the internally maintained state of each</span>135<a id="L28"></a><span class="comment">// thread. All ptrace calls must run in the monitor thread, so the</span>136<a id="L29"></a><span class="comment">// monitor executes closures received on the debugReq channel.</span>137<a id="L30"></a><span class="comment">//</span>138<a id="L31"></a><span class="comment">// As ptrace&#39;s documentation is somewhat light, this is heavily based</span>139<a id="L32"></a><span class="comment">// on information gleaned from the implementation of ptrace found at</span>140<a id="L33"></a><span class="comment">// http://lxr.linux.no/linux+v2.6.30/kernel/ptrace.c</span>141<a id="L34"></a><span class="comment">// http://lxr.linux.no/linux+v2.6.30/arch/x86/kernel/ptrace.c#L854</span>142<a id="L35"></a><span class="comment">// as well as experimentation and examination of gdb&#39;s behavior.</span>143<a id="L37"></a>const (144 <a id="L38"></a>trace = false;145 <a id="L39"></a>traceIP = false;146 <a id="L40"></a>traceMem = false;147<a id="L41"></a>)148<a id="L43"></a><span class="comment">/*</span>149<a id="L44"></a><span class="comment"> * Thread state</span>150<a id="L45"></a><span class="comment"> */</span>151<a id="L47"></a><span class="comment">// Each thread can be in one of the following set of states.</span>152<a id="L48"></a><span class="comment">// Each state satisfies</span>153<a id="L49"></a><span class="comment">// isRunning() || isStopped() || isZombie() || isTerminal().</span>154<a id="L50"></a><span class="comment">//</span>155<a id="L51"></a><span class="comment">// Running threads can be sent signals and must be waited on, but they</span>156<a id="L52"></a><span class="comment">// cannot be inspected using ptrace.</span>157<a id="L53"></a><span class="comment">//</span>158<a id="L54"></a><span class="comment">// Stopped threads can be inspected and continued, but cannot be</span>159<a id="L55"></a><span class="comment">// meaningfully waited on. They can be sent signals, but the signals</span>160<a id="L56"></a><span class="comment">// will be queued until they are running again.</span>161<a id="L57"></a><span class="comment">//</span>162<a id="L58"></a><span class="comment">// Zombie threads cannot be inspected, continued, or sent signals (and</span>163<a id="L59"></a><span class="comment">// therefore they cannot be stopped), but they must be waited on.</span>164<a id="L60"></a><span class="comment">//</span>165<a id="L61"></a><span class="comment">// Terminal threads no longer exist in the OS and thus you can&#39;t do</span>166<a id="L62"></a><span class="comment">// anything with them.</span>167<a id="L63"></a>type threadState string168<a id="L65"></a>const (169 <a id="L66"></a>running threadState = &#34;Running&#34;;170 <a id="L67"></a>singleStepping threadState = &#34;SingleStepping&#34;; <span class="comment">// Transient</span>171 <a id="L68"></a>stopping threadState = &#34;Stopping&#34;; <span class="comment">// Transient</span>172 <a id="L69"></a>stopped threadState = &#34;Stopped&#34;;173 <a id="L70"></a>stoppedBreakpoint threadState = &#34;StoppedBreakpoint&#34;;174 <a id="L71"></a>stoppedSignal threadState = &#34;StoppedSignal&#34;;175 <a id="L72"></a>stoppedThreadCreate threadState = &#34;StoppedThreadCreate&#34;;176 <a id="L73"></a>stoppedExiting threadState = &#34;StoppedExiting&#34;;177 <a id="L74"></a>exiting threadState = &#34;Exiting&#34;; <span class="comment">// Transient (except main thread)</span>178 <a id="L75"></a>exited threadState = &#34;Exited&#34;;179 <a id="L76"></a>detached threadState = &#34;Detached&#34;;180<a id="L77"></a>)181<a id="L79"></a>func (ts threadState) isRunning() bool {182 <a id="L80"></a>return ts == running || ts == singleStepping || ts == stopping183<a id="L81"></a>}184<a id="L83"></a>func (ts threadState) isStopped() bool {185 <a id="L84"></a>return ts == stopped || ts == stoppedBreakpoint || ts == stoppedSignal || ts == stoppedThreadCreate || ts == stoppedExiting186<a id="L85"></a>}187<a id="L87"></a>func (ts threadState) isZombie() bool { return ts == exiting }188<a id="L89"></a>func (ts threadState) isTerminal() bool { return ts == exited || ts == detached }189<a id="L91"></a>func (ts threadState) String() string { return string(ts) }190<a id="L93"></a><span class="comment">/*</span>191<a id="L94"></a><span class="comment"> * Basic types</span>192<a id="L95"></a><span class="comment"> */</span>193<a id="L97"></a><span class="comment">// A breakpoint stores information about a single breakpoint,</span>194<a id="L98"></a><span class="comment">// including its program counter, the overwritten text if the</span>195<a id="L99"></a><span class="comment">// breakpoint is installed.</span>196<a id="L100"></a>type breakpoint struct {197 <a id="L101"></a>pc uintptr;198 <a id="L102"></a>olddata []byte;199<a id="L103"></a>}200<a id="L105"></a>func (bp *breakpoint) String() string {201 <a id="L106"></a>if bp == nil {202 <a id="L107"></a>return &#34;&lt;nil&gt;&#34;203 <a id="L108"></a>}204 <a id="L109"></a>return fmt.Sprintf(&#34;%#x&#34;, bp.pc);205<a id="L110"></a>}206<a id="L112"></a><span class="comment">// bpinst386 is the breakpoint instruction used on 386 and amd64.</span>207<a id="L113"></a>var bpinst386 = []byte{0xcc}208<a id="L115"></a><span class="comment">// A debugEvent represents a reason a thread stopped or a wait error.</span>209<a id="L116"></a>type debugEvent struct {210 <a id="L117"></a>*os.Waitmsg;211 <a id="L118"></a>t *thread;212 <a id="L119"></a>err os.Error;213<a id="L120"></a>}214<a id="L122"></a><span class="comment">// A debugReq is a request to execute a closure in the monitor thread.</span>215<a id="L123"></a>type debugReq struct {216 <a id="L124"></a>f func() os.Error;217 <a id="L125"></a>res chan os.Error;218<a id="L126"></a>}219<a id="L128"></a><span class="comment">// A transitionHandler specifies a function to be called when a thread</span>220<a id="L129"></a><span class="comment">// changes state and a function to be called when an error occurs in</span>221<a id="L130"></a><span class="comment">// the monitor. Both run in the monitor thread. Before the monitor</span>222<a id="L131"></a><span class="comment">// invokes a handler, it removes the handler from the handler queue.</span>223<a id="L132"></a><span class="comment">// The handler should re-add itself if needed.</span>224<a id="L133"></a>type transitionHandler struct {225 <a id="L134"></a>handle func(*thread, threadState, threadState);226 <a id="L135"></a>onErr func(os.Error);227<a id="L136"></a>}228<a id="L138"></a><span class="comment">// A process is a Linux process, which consists of a set of threads.</span>229<a id="L139"></a><span class="comment">// Each running process has one monitor thread, which processes</span>230<a id="L140"></a><span class="comment">// messages from the debugEvents, debugReqs, and stopReq channels and</span>231<a id="L141"></a><span class="comment">// calls transition handlers.</span>232<a id="L142"></a><span class="comment">//</span>233<a id="L143"></a><span class="comment">// To send a message to the monitor thread, first receive from the</span>234<a id="L144"></a><span class="comment">// ready channel. If the ready channel returns true, the monitor is</span>235<a id="L145"></a><span class="comment">// still running and will accept a message. If the ready channel</span>236<a id="L146"></a><span class="comment">// returns false, the monitor is not running (the ready channel has</span>237<a id="L147"></a><span class="comment">// been closed), and the reason it is not running will be stored in err.</span>238<a id="L148"></a>type process struct {239 <a id="L149"></a>pid int;240 <a id="L150"></a>threads map[int]*thread;241 <a id="L151"></a>breakpoints map[uintptr]*breakpoint;242 <a id="L152"></a>ready chan bool;243 <a id="L153"></a>debugEvents chan *debugEvent;244 <a id="L154"></a>debugReqs chan *debugReq;245 <a id="L155"></a>stopReq chan os.Error;246 <a id="L156"></a>transitionHandlers *vector.Vector;247 <a id="L157"></a>err os.Error;248<a id="L158"></a>}249<a id="L160"></a><span class="comment">// A thread represents a Linux thread in another process that is being</span>250<a id="L161"></a><span class="comment">// debugged. Each running thread has an associated goroutine that</span>251<a id="L162"></a><span class="comment">// waits for thread updates and sends them to the process monitor.</span>252<a id="L163"></a>type thread struct {253 <a id="L164"></a>tid int;254 <a id="L165"></a>proc *process;255 <a id="L166"></a><span class="comment">// Whether to ignore the next SIGSTOP received by wait.</span>256 <a id="L167"></a>ignoreNextSigstop bool;257 <a id="L169"></a><span class="comment">// Thread state. Only modified via setState.</span>258 <a id="L170"></a>state threadState;259 <a id="L171"></a><span class="comment">// If state == StoppedBreakpoint</span>260 <a id="L172"></a>breakpoint *breakpoint;261 <a id="L173"></a><span class="comment">// If state == StoppedSignal or state == Exited</span>262 <a id="L174"></a>signal int;263 <a id="L175"></a><span class="comment">// If state == StoppedThreadCreate</span>264 <a id="L176"></a>newThread *thread;265 <a id="L177"></a><span class="comment">// If state == Exited</span>266 <a id="L178"></a>exitStatus int;267<a id="L179"></a>}268<a id="L181"></a><span class="comment">/*</span>269<a id="L182"></a><span class="comment"> * Errors</span>270<a id="L183"></a><span class="comment"> */</span>271<a id="L185"></a>type badState struct {272 <a id="L186"></a>thread *thread;273 <a id="L187"></a>message string;274 <a id="L188"></a>state threadState;275<a id="L189"></a>}276<a id="L191"></a>func (e *badState) String() string {277 <a id="L192"></a>return fmt.Sprintf(&#34;Thread %d %s from state %v&#34;, e.thread.tid, e.message, e.state)278<a id="L193"></a>}279<a id="L195"></a>type breakpointExistsError Word280<a id="L197"></a>func (e breakpointExistsError) String() string {281 <a id="L198"></a>return fmt.Sprintf(&#34;breakpoint already exists at PC %#x&#34;, e)282<a id="L199"></a>}283<a id="L201"></a>type noBreakpointError Word284<a id="L203"></a>func (e noBreakpointError) String() string { return fmt.Sprintf(&#34;no breakpoint at PC %#x&#34;, e) }285<a id="L205"></a>type newThreadError struct {286 <a id="L206"></a>*os.Waitmsg;287 <a id="L207"></a>wantPid int;288 <a id="L208"></a>wantSig int;289<a id="L209"></a>}290<a id="L211"></a>func (e *newThreadError) String() string {291 <a id="L212"></a>return fmt.Sprintf(&#34;newThread wait wanted pid %v and signal %v, got %v and %v&#34;, e.Pid, e.StopSignal(), e.wantPid, e.wantSig)292<a id="L213"></a>}293<a id="L215"></a>type ProcessExited struct{}294<a id="L217"></a>func (p ProcessExited) String() string { return &#34;process exited&#34; }295<a id="L219"></a><span class="comment">/*</span>296<a id="L220"></a><span class="comment"> * Ptrace wrappers</span>297<a id="L221"></a><span class="comment"> */</span>298<a id="L223"></a>func (t *thread) ptracePeekText(addr uintptr, out []byte) (int, os.Error) {299 <a id="L224"></a>c, err := syscall.PtracePeekText(t.tid, addr, out);300 <a id="L225"></a>if traceMem {301 <a id="L226"></a>fmt.Printf(&#34;peek(%#x) =&gt; %v, %v\n&#34;, addr, out, err)302 <a id="L227"></a>}303 <a id="L228"></a>return c, os.NewSyscallError(&#34;ptrace(PEEKTEXT)&#34;, err);304<a id="L229"></a>}305<a id="L231"></a>func (t *thread) ptracePokeText(addr uintptr, out []byte) (int, os.Error) {306 <a id="L232"></a>c, err := syscall.PtracePokeText(t.tid, addr, out);307 <a id="L233"></a>if traceMem {308 <a id="L234"></a>fmt.Printf(&#34;poke(%#x, %v) =&gt; %v\n&#34;, addr, out, err)309 <a id="L235"></a>}310 <a id="L236"></a>return c, os.NewSyscallError(&#34;ptrace(POKETEXT)&#34;, err);311<a id="L237"></a>}312<a id="L239"></a>func (t *thread) ptraceGetRegs(regs *syscall.PtraceRegs) os.Error {313 <a id="L240"></a>err := syscall.PtraceGetRegs(t.tid, regs);314 <a id="L241"></a>return os.NewSyscallError(&#34;ptrace(GETREGS)&#34;, err);315<a id="L242"></a>}316<a id="L244"></a>func (t *thread) ptraceSetRegs(regs *syscall.PtraceRegs) os.Error {317 <a id="L245"></a>err := syscall.PtraceSetRegs(t.tid, regs);318 <a id="L246"></a>return os.NewSyscallError(&#34;ptrace(SETREGS)&#34;, err);319<a id="L247"></a>}320<a id="L249"></a>func (t *thread) ptraceSetOptions(options int) os.Error {321 <a id="L250"></a>err := syscall.PtraceSetOptions(t.tid, options);322 <a id="L251"></a>return os.NewSyscallError(&#34;ptrace(SETOPTIONS)&#34;, err);323<a id="L252"></a>}324<a id="L254"></a>func (t *thread) ptraceGetEventMsg() (uint, os.Error) {325 <a id="L255"></a>msg, err := syscall.PtraceGetEventMsg(t.tid);326 <a id="L256"></a>return msg, os.NewSyscallError(&#34;ptrace(GETEVENTMSG)&#34;, err);327<a id="L257"></a>}328<a id="L259"></a>func (t *thread) ptraceCont() os.Error {329 <a id="L260"></a>err := syscall.PtraceCont(t.tid, 0);330 <a id="L261"></a>return os.NewSyscallError(&#34;ptrace(CONT)&#34;, err);331<a id="L262"></a>}332<a id="L264"></a>func (t *thread) ptraceContWithSignal(sig int) os.Error {333 <a id="L265"></a>err := syscall.PtraceCont(t.tid, sig);334 <a id="L266"></a>return os.NewSyscallError(&#34;ptrace(CONT)&#34;, err);335<a id="L267"></a>}336<a id="L269"></a>func (t *thread) ptraceStep() os.Error {337 <a id="L270"></a>err := syscall.PtraceSingleStep(t.tid);338 <a id="L271"></a>return os.NewSyscallError(&#34;ptrace(SINGLESTEP)&#34;, err);339<a id="L272"></a>}340<a id="L274"></a>func (t *thread) ptraceDetach() os.Error {341 <a id="L275"></a>err := syscall.PtraceDetach(t.tid);342 <a id="L276"></a>return os.NewSyscallError(&#34;ptrace(DETACH)&#34;, err);343<a id="L277"></a>}344<a id="L279"></a><span class="comment">/*</span>345<a id="L280"></a><span class="comment"> * Logging utilties</span>346<a id="L281"></a><span class="comment"> */</span>347<a id="L283"></a>var logLock sync.Mutex348<a id="L285"></a>func (t *thread) logTrace(format string, args ...) {349 <a id="L286"></a>if !trace {350 <a id="L287"></a>return351 <a id="L288"></a>}352 <a id="L289"></a>logLock.Lock();353 <a id="L290"></a>defer logLock.Unlock();354 <a id="L291"></a>fmt.Fprintf(os.Stderr, &#34;Thread %d&#34;, t.tid);355 <a id="L292"></a>if traceIP {356 <a id="L293"></a>var regs syscall.PtraceRegs;357 <a id="L294"></a>err := t.ptraceGetRegs(&amp;regs);358 <a id="L295"></a>if err == nil {359 <a id="L296"></a>fmt.Fprintf(os.Stderr, &#34;@%x&#34;, regs.PC())360 <a id="L297"></a>}361 <a id="L298"></a>}362 <a id="L299"></a>fmt.Fprint(os.Stderr, &#34;: &#34;);363 <a id="L300"></a>fmt.Fprintf(os.Stderr, format, args);364 <a id="L301"></a>fmt.Fprint(os.Stderr, &#34;\n&#34;);365<a id="L302"></a>}366<a id="L304"></a>func (t *thread) warn(format string, args ...) {367 <a id="L305"></a>logLock.Lock();368 <a id="L306"></a>defer logLock.Unlock();369 <a id="L307"></a>fmt.Fprintf(os.Stderr, &#34;Thread %d: WARNING &#34;, t.tid);370 <a id="L308"></a>fmt.Fprintf(os.Stderr, format, args);371 <a id="L309"></a>fmt.Fprint(os.Stderr, &#34;\n&#34;);372<a id="L310"></a>}373<a id="L312"></a>func (p *process) logTrace(format string, args ...) {374 <a id="L313"></a>if !trace {375 <a id="L314"></a>return376 <a id="L315"></a>}377 <a id="L316"></a>logLock.Lock();378 <a id="L317"></a>defer logLock.Unlock();379 <a id="L318"></a>fmt.Fprintf(os.Stderr, &#34;Process %d: &#34;, p.pid);380 <a id="L319"></a>fmt.Fprintf(os.Stderr, format, args);381 <a id="L320"></a>fmt.Fprint(os.Stderr, &#34;\n&#34;);382<a id="L321"></a>}383<a id="L323"></a><span class="comment">/*</span>384<a id="L324"></a><span class="comment"> * State utilities</span>385<a id="L325"></a><span class="comment"> */</span>386<a id="L327"></a><span class="comment">// someStoppedThread returns a stopped thread from the process.</span>387<a id="L328"></a><span class="comment">// Returns nil if no threads are stopped.</span>388<a id="L329"></a><span class="comment">//</span>389<a id="L330"></a><span class="comment">// Must be called from the monitor thread.</span>390<a id="L331"></a>func (p *process) someStoppedThread() *thread {391 <a id="L332"></a>for _, t := range p.threads {392 <a id="L333"></a>if t.state.isStopped() {393 <a id="L334"></a>return t394 <a id="L335"></a>}395 <a id="L336"></a>}396 <a id="L337"></a>return nil;397<a id="L338"></a>}398<a id="L340"></a><span class="comment">// someRunningThread returns a running thread from the process.</span>399<a id="L341"></a><span class="comment">// Returns nil if no threads are running.</span>400<a id="L342"></a><span class="comment">//</span>401<a id="L343"></a><span class="comment">// Must be called from the monitor thread.</span>402<a id="L344"></a>func (p *process) someRunningThread() *thread {403 <a id="L345"></a>for _, t := range p.threads {404 <a id="L346"></a>if t.state.isRunning() {405 <a id="L347"></a>return t406 <a id="L348"></a>}407 <a id="L349"></a>}408 <a id="L350"></a>return nil;409<a id="L351"></a>}410<a id="L353"></a><span class="comment">/*</span>411<a id="L354"></a><span class="comment"> * Breakpoint utilities</span>412<a id="L355"></a><span class="comment"> */</span>413<a id="L357"></a><span class="comment">// installBreakpoints adds breakpoints to the attached process.</span>414<a id="L358"></a><span class="comment">//</span>415<a id="L359"></a><span class="comment">// Must be called from the monitor thread.</span>416<a id="L360"></a>func (p *process) installBreakpoints() os.Error {417 <a id="L361"></a>n := 0;418 <a id="L362"></a>main := p.someStoppedThread();419 <a id="L363"></a>for _, b := range p.breakpoints {420 <a id="L364"></a>if b.olddata != nil {421 <a id="L365"></a>continue422 <a id="L366"></a>}423 <a id="L368"></a>b.olddata = make([]byte, len(bpinst386));424 <a id="L369"></a>_, err := main.ptracePeekText(uintptr(b.pc), b.olddata);425 <a id="L370"></a>if err != nil {426 <a id="L371"></a>b.olddata = nil;427 <a id="L372"></a>return err;428 <a id="L373"></a>}429 <a id="L375"></a>_, err = main.ptracePokeText(uintptr(b.pc), bpinst386);430 <a id="L376"></a>if err != nil {431 <a id="L377"></a>b.olddata = nil;432 <a id="L378"></a>return err;433 <a id="L379"></a>}434 <a id="L380"></a>n++;435 <a id="L381"></a>}436 <a id="L382"></a>if n &gt; 0 {437 <a id="L383"></a>p.logTrace(&#34;installed %d/%d breakpoints&#34;, n, len(p.breakpoints))438 <a id="L384"></a>}439 <a id="L386"></a>return nil;440<a id="L387"></a>}441<a id="L389"></a><span class="comment">// uninstallBreakpoints removes the installed breakpoints from p.</span>442<a id="L390"></a><span class="comment">//</span>443<a id="L391"></a><span class="comment">// Must be called from the monitor thread.</span>444<a id="L392"></a>func (p *process) uninstallBreakpoints() os.Error {445 <a id="L393"></a>if len(p.threads) == 0 {446 <a id="L394"></a>return nil447 <a id="L395"></a>}448 <a id="L396"></a>n := 0;449 <a id="L397"></a>main := p.someStoppedThread();450 <a id="L398"></a>for _, b := range p.breakpoints {451 <a id="L399"></a>if b.olddata == nil {452 <a id="L400"></a>continue453 <a id="L401"></a>}454 <a id="L403"></a>_, err := main.ptracePokeText(uintptr(b.pc), b.olddata);455 <a id="L404"></a>if err != nil {456 <a id="L405"></a>return err457 <a id="L406"></a>}458 <a id="L407"></a>b.olddata = nil;459 <a id="L408"></a>n++;460 <a id="L409"></a>}461 <a id="L410"></a>if n &gt; 0 {462 <a id="L411"></a>p.logTrace(&#34;uninstalled %d/%d breakpoints&#34;, n, len(p.breakpoints))463 <a id="L412"></a>}464 <a id="L414"></a>return nil;465<a id="L415"></a>}466<a id="L417"></a><span class="comment">/*</span>467<a id="L418"></a><span class="comment"> * Debug event handling</span>468<a id="L419"></a><span class="comment"> */</span>469<a id="L421"></a><span class="comment">// wait waits for a wait event from this thread and sends it on the</span>470<a id="L422"></a><span class="comment">// debug events channel for this thread&#39;s process. This should be</span>471<a id="L423"></a><span class="comment">// started in its own goroutine when the attached thread enters a</span>472<a id="L424"></a><span class="comment">// running state. The goroutine will exit as soon as it sends a debug</span>473<a id="L425"></a><span class="comment">// event.</span>474<a id="L426"></a>func (t *thread) wait() {475 <a id="L427"></a>for {476 <a id="L428"></a>var ev debugEvent;477 <a id="L429"></a>ev.t = t;478 <a id="L430"></a>t.logTrace(&#34;beginning wait&#34;);479 <a id="L431"></a>ev.Waitmsg, ev.err = os.Wait(t.tid, syscall.WALL);480 <a id="L432"></a>if ev.err == nil &amp;&amp; ev.Pid != t.tid {481 <a id="L433"></a>panic(&#34;Wait returned pid &#34;, ev.Pid, &#34; wanted &#34;, t.tid)482 <a id="L434"></a>}483 <a id="L435"></a>if ev.StopSignal() == syscall.SIGSTOP &amp;&amp; t.ignoreNextSigstop {484 <a id="L436"></a><span class="comment">// Spurious SIGSTOP. See Thread.Stop().</span>485 <a id="L437"></a>t.ignoreNextSigstop = false;486 <a id="L438"></a>err := t.ptraceCont();487 <a id="L439"></a>if err == nil {488 <a id="L440"></a>continue489 <a id="L441"></a>}490 <a id="L442"></a><span class="comment">// If we failed to continue, just let</span>491 <a id="L443"></a><span class="comment">// the stop go through so we can</span>492 <a id="L444"></a><span class="comment">// update the thread&#39;s state.</span>493 <a id="L445"></a>}494 <a id="L446"></a>if !&lt;-t.proc.ready {495 <a id="L447"></a><span class="comment">// The monitor exited</span>496 <a id="L448"></a>break497 <a id="L449"></a>}498 <a id="L450"></a>t.proc.debugEvents &lt;- &amp;ev;499 <a id="L451"></a>break;500 <a id="L452"></a>}501<a id="L453"></a>}502<a id="L455"></a><span class="comment">// setState sets this thread&#39;s state, starts a wait thread if</span>503<a id="L456"></a><span class="comment">// necessary, and invokes state transition handlers.</span>504<a id="L457"></a><span class="comment">//</span>505<a id="L458"></a><span class="comment">// Must be called from the monitor thread.</span>506<a id="L459"></a>func (t *thread) setState(new threadState) {507 <a id="L460"></a>old := t.state;508 <a id="L461"></a>t.state = new;509 <a id="L462"></a>t.logTrace(&#34;state %v -&gt; %v&#34;, old, new);510 <a id="L464"></a>if !old.isRunning() &amp;&amp; (new.isRunning() || new.isZombie()) {511 <a id="L465"></a><span class="comment">// Start waiting on this thread</span>512 <a id="L466"></a>go t.wait()513 <a id="L467"></a>}514 <a id="L469"></a><span class="comment">// Invoke state change handlers</span>515 <a id="L470"></a>handlers := t.proc.transitionHandlers;516 <a id="L471"></a>if handlers.Len() == 0 {517 <a id="L472"></a>return518 <a id="L473"></a>}519 <a id="L475"></a>t.proc.transitionHandlers = vector.New(0);520 <a id="L476"></a>for _, h := range handlers.Data() {521 <a id="L477"></a>h := h.(*transitionHandler);522 <a id="L478"></a>h.handle(t, old, new);523 <a id="L479"></a>}524<a id="L480"></a>}525<a id="L482"></a><span class="comment">// sendSigstop sends a SIGSTOP to this thread.</span>526<a id="L483"></a>func (t *thread) sendSigstop() os.Error {527 <a id="L484"></a>t.logTrace(&#34;sending SIGSTOP&#34;);528 <a id="L485"></a>err := syscall.Tgkill(t.proc.pid, t.tid, syscall.SIGSTOP);529 <a id="L486"></a>return os.NewSyscallError(&#34;tgkill&#34;, err);530<a id="L487"></a>}531<a id="L489"></a><span class="comment">// stopAsync sends SIGSTOP to all threads in state &#39;running&#39;.</span>532<a id="L490"></a><span class="comment">//</span>533<a id="L491"></a><span class="comment">// Must be called from the monitor thread.</span>534<a id="L492"></a>func (p *process) stopAsync() os.Error {535 <a id="L493"></a>for _, t := range p.threads {536 <a id="L494"></a>if t.state == running {537 <a id="L495"></a>err := t.sendSigstop();538 <a id="L496"></a>if err != nil {539 <a id="L497"></a>return err540 <a id="L498"></a>}541 <a id="L499"></a>t.setState(stopping);542 <a id="L500"></a>}543 <a id="L501"></a>}544 <a id="L502"></a>return nil;545<a id="L503"></a>}546<a id="L505"></a><span class="comment">// doTrap handles SIGTRAP debug events with a cause of 0. These can</span>547<a id="L506"></a><span class="comment">// be caused either by an installed breakpoint, a breakpoint in the</span>548<a id="L507"></a><span class="comment">// program text, or by single stepping.</span>549<a id="L508"></a><span class="comment">//</span>550<a id="L509"></a><span class="comment">// TODO(austin) I think we also get this on an execve syscall.</span>551<a id="L510"></a>func (ev *debugEvent) doTrap() (threadState, os.Error) {552 <a id="L511"></a>t := ev.t;553 <a id="L513"></a>if t.state == singleStepping {554 <a id="L514"></a>return stopped, nil555 <a id="L515"></a>}556 <a id="L517"></a><span class="comment">// Hit a breakpoint. Linux leaves the program counter after</span>557 <a id="L518"></a><span class="comment">// the breakpoint. If this is an installed breakpoint, we</span>558 <a id="L519"></a><span class="comment">// need to back the PC up to the breakpoint PC.</span>559 <a id="L520"></a>var regs syscall.PtraceRegs;560 <a id="L521"></a>err := t.ptraceGetRegs(&amp;regs);561 <a id="L522"></a>if err != nil {562 <a id="L523"></a>return stopped, err563 <a id="L524"></a>}564 <a id="L526"></a>b, ok := t.proc.breakpoints[uintptr(regs.PC())-uintptr(len(bpinst386))];565 <a id="L527"></a>if !ok {566 <a id="L528"></a><span class="comment">// We must have hit a breakpoint that was actually in</span>567 <a id="L529"></a><span class="comment">// the program. Leave the IP where it is so we don&#39;t</span>568 <a id="L530"></a><span class="comment">// re-execute the breakpoint instruction. Expose the</span>569 <a id="L531"></a><span class="comment">// fact that we stopped with a SIGTRAP.</span>570 <a id="L532"></a>return stoppedSignal, nil571 <a id="L533"></a>}572 <a id="L535"></a>t.breakpoint = b;573 <a id="L536"></a>t.logTrace(&#34;at breakpoint %v, backing up PC from %#x&#34;, b, regs.PC());574 <a id="L538"></a>regs.SetPC(uint64(b.pc));575 <a id="L539"></a>err = t.ptraceSetRegs(&amp;regs);576 <a id="L540"></a>if err != nil {577 <a id="L541"></a>return stopped, err578 <a id="L542"></a>}579 <a id="L543"></a>return stoppedBreakpoint, nil;580<a id="L544"></a>}581<a id="L546"></a><span class="comment">// doPtraceClone handles SIGTRAP debug events with a PTRACE_EVENT_CLONE</span>582<a id="L547"></a><span class="comment">// cause. It initializes the new thread, adds it to the process, and</span>583<a id="L548"></a><span class="comment">// returns the appropriate thread state for the existing thread.</span>584<a id="L549"></a>func (ev *debugEvent) doPtraceClone() (threadState, os.Error) {585 <a id="L550"></a>t := ev.t;586 <a id="L552"></a><span class="comment">// Get the TID of the new thread</span>587 <a id="L553"></a>tid, err := t.ptraceGetEventMsg();588 <a id="L554"></a>if err != nil {589 <a id="L555"></a>return stopped, err590 <a id="L556"></a>}591 <a id="L558"></a>nt, err := t.proc.newThread(int(tid), syscall.SIGSTOP, true);592 <a id="L559"></a>if err != nil {593 <a id="L560"></a>return stopped, err594 <a id="L561"></a>}595 <a id="L563"></a><span class="comment">// Remember the thread</span>596 <a id="L564"></a>t.newThread = nt;597 <a id="L566"></a>return stoppedThreadCreate, nil;598<a id="L567"></a>}599<a id="L569"></a><span class="comment">// doPtraceExit handles SIGTRAP debug events with a PTRACE_EVENT_EXIT</span>600<a id="L570"></a><span class="comment">// cause. It sets up the thread&#39;s state, but does not remove it from</span>601<a id="L571"></a><span class="comment">// the process. A later WIFEXITED debug event will remove it from the</span>602<a id="L572"></a><span class="comment">// process.</span>603<a id="L573"></a>func (ev *debugEvent) doPtraceExit() (threadState, os.Error) {604 <a id="L574"></a>t := ev.t;605 <a id="L576"></a><span class="comment">// Get exit status</span>606 <a id="L577"></a>exitStatus, err := t.ptraceGetEventMsg();607 <a id="L578"></a>if err != nil {608 <a id="L579"></a>return stopped, err609 <a id="L580"></a>}610 <a id="L581"></a>ws := syscall.WaitStatus(exitStatus);611 <a id="L582"></a>t.logTrace(&#34;exited with %v&#34;, ws);612 <a id="L583"></a>switch {613 <a id="L584"></a>case ws.Exited():614 <a id="L585"></a>t.exitStatus = ws.ExitStatus()615 <a id="L586"></a>case ws.Signaled():616 <a id="L587"></a>t.signal = ws.Signal()617 <a id="L588"></a>}618 <a id="L590"></a><span class="comment">// We still need to continue this thread and wait on this</span>619 <a id="L591"></a><span class="comment">// thread&#39;s WIFEXITED event. We&#39;ll delete it then.</span>620 <a id="L592"></a>return stoppedExiting, nil;621<a id="L593"></a>}622<a id="L595"></a><span class="comment">// process handles a debug event. It modifies any thread or process</span>623<a id="L596"></a><span class="comment">// state as necessary, uninstalls breakpoints if necessary, and stops</span>624<a id="L597"></a><span class="comment">// any running threads.</span>625<a id="L598"></a>func (ev *debugEvent) process() os.Error {626 <a id="L599"></a>if ev.err != nil {627 <a id="L600"></a>return ev.err628 <a id="L601"></a>}629 <a id="L603"></a>t := ev.t;630 <a id="L604"></a>t.exitStatus = -1;631 <a id="L605"></a>t.signal = -1;632 <a id="L607"></a><span class="comment">// Decode wait status.</span>633 <a id="L608"></a>var state threadState;634 <a id="L609"></a>switch {635 <a id="L610"></a>case ev.Stopped():636 <a id="L611"></a>state = stoppedSignal;637 <a id="L612"></a>t.signal = ev.StopSignal();638 <a id="L613"></a>t.logTrace(&#34;stopped with %v&#34;, ev);639 <a id="L614"></a>if ev.StopSignal() == syscall.SIGTRAP {640 <a id="L615"></a><span class="comment">// What caused the debug trap?</span>641 <a id="L616"></a>var err os.Error;642 <a id="L617"></a>switch cause := ev.TrapCause(); cause {643 <a id="L618"></a>case 0:644 <a id="L619"></a><span class="comment">// Breakpoint or single stepping</span>645 <a id="L620"></a>state, err = ev.doTrap()646 <a id="L622"></a>case syscall.PTRACE_EVENT_CLONE:647 <a id="L623"></a>state, err = ev.doPtraceClone()648 <a id="L625"></a>case syscall.PTRACE_EVENT_EXIT:649 <a id="L626"></a>state, err = ev.doPtraceExit()650 <a id="L628"></a>default:651 <a id="L629"></a>t.warn(&#34;Unknown trap cause %d&#34;, cause)652 <a id="L630"></a>}653 <a id="L632"></a>if err != nil {654 <a id="L633"></a>t.setState(stopped);655 <a id="L634"></a>t.warn(&#34;failed to handle trap %v: %v&#34;, ev, err);656 <a id="L635"></a>}657 <a id="L636"></a>}658 <a id="L638"></a>case ev.Exited():659 <a id="L639"></a>state = exited;660 <a id="L640"></a>t.proc.threads[t.tid] = nil, false;661 <a id="L641"></a>t.logTrace(&#34;exited %v&#34;, ev);662 <a id="L642"></a><span class="comment">// We should have gotten the exit status in</span>663 <a id="L643"></a><span class="comment">// PTRACE_EVENT_EXIT, but just in case.</span>664 <a id="L644"></a>t.exitStatus = ev.ExitStatus();665 <a id="L646"></a>case ev.Signaled():666 <a id="L647"></a>state = exited;667 <a id="L648"></a>t.proc.threads[t.tid] = nil, false;668 <a id="L649"></a>t.logTrace(&#34;signaled %v&#34;, ev);669 <a id="L650"></a><span class="comment">// Again, this should be redundant.</span>670 <a id="L651"></a>t.signal = ev.Signal();671 <a id="L653"></a>default:672 <a id="L654"></a>panic(fmt.Sprintf(&#34;Unexpected wait status %v&#34;, ev.Waitmsg))673 <a id="L655"></a>}674 <a id="L657"></a><span class="comment">// If we sent a SIGSTOP to the thread (indicated by state</span>675 <a id="L658"></a><span class="comment">// Stopping), we might have raced with a different type of</span>676 <a id="L659"></a><span class="comment">// stop. If we didn&#39;t get the stop we expected, then the</span>677 <a id="L660"></a><span class="comment">// SIGSTOP we sent is now queued up, so we should ignore the</span>678 <a id="L661"></a><span class="comment">// next one we get.</span>679 <a id="L662"></a>if t.state == stopping &amp;&amp; ev.StopSignal() != syscall.SIGSTOP {680 <a id="L663"></a>t.ignoreNextSigstop = true681 <a id="L664"></a>}682 <a id="L666"></a><span class="comment">// TODO(austin) If we&#39;re in state stopping and get a SIGSTOP,</span>683 <a id="L667"></a><span class="comment">// set state stopped instead of stoppedSignal.</span>684 <a id="L669"></a>t.setState(state);685 <a id="L671"></a>if t.proc.someRunningThread() == nil {686 <a id="L672"></a><span class="comment">// Nothing is running, uninstall breakpoints</span>687 <a id="L673"></a>return t.proc.uninstallBreakpoints()688 <a id="L674"></a>}689 <a id="L675"></a><span class="comment">// Stop any other running threads</span>690 <a id="L676"></a>return t.proc.stopAsync();691<a id="L677"></a>}692<a id="L679"></a><span class="comment">// onStop adds a handler for state transitions from running to</span>693<a id="L680"></a><span class="comment">// non-running states. The handler will be called from the monitor</span>694<a id="L681"></a><span class="comment">// thread.</span>695<a id="L682"></a><span class="comment">//</span>696<a id="L683"></a><span class="comment">// Must be called from the monitor thread.</span>697<a id="L684"></a>func (t *thread) onStop(handle func(), onErr func(os.Error)) {698 <a id="L685"></a><span class="comment">// TODO(austin) This is rather inefficient for things like</span>699 <a id="L686"></a><span class="comment">// stepping all threads during a continue. Maybe move</span>700 <a id="L687"></a><span class="comment">// transitionHandlers to the thread, or have both per-thread</span>701 <a id="L688"></a><span class="comment">// and per-process transition handlers.</span>702 <a id="L689"></a>h := &amp;transitionHandler{nil, onErr};703 <a id="L690"></a>h.handle = func(st *thread, old, new threadState) {704 <a id="L691"></a>if t == st &amp;&amp; old.isRunning() &amp;&amp; !new.isRunning() {705 <a id="L692"></a>handle()706 <a id="L693"></a>} else {707 <a id="L694"></a>t.proc.transitionHandlers.Push(h)708 <a id="L695"></a>}709 <a id="L696"></a>};710 <a id="L697"></a>t.proc.transitionHandlers.Push(h);711<a id="L698"></a>}712<a id="L700"></a><span class="comment">/*</span>713<a id="L701"></a><span class="comment"> * Event monitor</span>714<a id="L702"></a><span class="comment"> */</span>715<a id="L704"></a><span class="comment">// monitor handles debug events and debug requests for p, exiting when</span>716<a id="L705"></a><span class="comment">// there are no threads left in p.</span>717<a id="L706"></a>func (p *process) monitor() {718 <a id="L707"></a>var err os.Error;719 <a id="L709"></a><span class="comment">// Linux requires that all ptrace calls come from the thread</span>720 <a id="L710"></a><span class="comment">// that originally attached. Prevent the Go scheduler from</span>721 <a id="L711"></a><span class="comment">// migrating us to other OS threads.</span>722 <a id="L712"></a>runtime.LockOSThread();723 <a id="L713"></a>defer runtime.UnlockOSThread();724 <a id="L715"></a>hadThreads := false;725 <a id="L716"></a>for err == nil {726 <a id="L717"></a>p.ready &lt;- true;727 <a id="L718"></a>select {728 <a id="L719"></a>case event := &lt;-p.debugEvents:729 <a id="L720"></a>err = event.process()730 <a id="L722"></a>case req := &lt;-p.debugReqs:731 <a id="L723"></a>req.res &lt;- req.f()732 <a id="L725"></a>case err = &lt;-p.stopReq:733 <a id="L726"></a>break734 <a id="L727"></a>}735 <a id="L729"></a>if len(p.threads) == 0 {736 <a id="L730"></a>if err == nil &amp;&amp; hadThreads {737 <a id="L731"></a>p.logTrace(&#34;no more threads; monitor exiting&#34;);738 <a id="L732"></a>err = ProcessExited{};739 <a id="L733"></a>}740 <a id="L734"></a>} else {741 <a id="L735"></a>hadThreads = true742 <a id="L736"></a>}743 <a id="L737"></a>}744 <a id="L739"></a><span class="comment">// Abort waiting handlers</span>745 <a id="L740"></a><span class="comment">// TODO(austin) How do I stop the wait threads?</span>746 <a id="L741"></a>for _, h := range p.transitionHandlers.Data() {747 <a id="L742"></a>h := h.(*transitionHandler);748 <a id="L743"></a>h.onErr(err);749 <a id="L744"></a>}750 <a id="L746"></a><span class="comment">// Indicate that the monitor cannot receive any more messages</span>751 <a id="L747"></a>p.err = err;752 <a id="L748"></a>close(p.ready);753<a id="L749"></a>}754<a id="L751"></a><span class="comment">// do executes f in the monitor thread (and, thus, atomically with</span>755<a id="L752"></a><span class="comment">// respect to thread state changes). f must not block.</span>756<a id="L753"></a><span class="comment">//</span>757<a id="L754"></a><span class="comment">// Must NOT be called from the monitor thread.</span>758<a id="L755"></a>func (p *process) do(f func() os.Error) os.Error {759 <a id="L756"></a>if !&lt;-p.ready {760 <a id="L757"></a>return p.err761 <a id="L758"></a>}762 <a id="L759"></a>req := &amp;debugReq{f, make(chan os.Error)};763 <a id="L760"></a>p.debugReqs &lt;- req;764 <a id="L761"></a>return &lt;-req.res;765<a id="L762"></a>}766<a id="L764"></a><span class="comment">// stopMonitor stops the monitor with the given error. If the monitor</span>767<a id="L765"></a><span class="comment">// is already stopped, does nothing.</span>768<a id="L766"></a>func (p *process) stopMonitor(err os.Error) {769 <a id="L767"></a>if err == nil {770 <a id="L768"></a>panic(&#34;cannot stop the monitor with no error&#34;)771 <a id="L769"></a>}772 <a id="L770"></a>if &lt;-p.ready {773 <a id="L771"></a>p.stopReq &lt;- err774 <a id="L772"></a>}775<a id="L773"></a>}776<a id="L775"></a><span class="comment">/*</span>777<a id="L776"></a><span class="comment"> * Public thread interface</span>778<a id="L777"></a><span class="comment"> */</span>779<a id="L779"></a>func (t *thread) Regs() (Regs, os.Error) {780 <a id="L780"></a>var regs syscall.PtraceRegs;781 <a id="L782"></a>err := t.proc.do(func() os.Error {782 <a id="L783"></a>if !t.state.isStopped() {783 <a id="L784"></a>return &amp;badState{t, &#34;cannot get registers&#34;, t.state}784 <a id="L785"></a>}785 <a id="L786"></a>return t.ptraceGetRegs(&amp;regs);786 <a id="L787"></a>});787 <a id="L788"></a>if err != nil {788 <a id="L789"></a>return nil, err789 <a id="L790"></a>}790 <a id="L792"></a>setter := func(r *syscall.PtraceRegs) os.Error {791 <a id="L793"></a>return t.proc.do(func() os.Error {792 <a id="L794"></a>if !t.state.isStopped() {793 <a id="L795"></a>return &amp;badState{t, &#34;cannot get registers&#34;, t.state}794 <a id="L796"></a>}795 <a id="L797"></a>return t.ptraceSetRegs(r);796 <a id="L798"></a>})797 <a id="L799"></a>};798 <a id="L800"></a>return newRegs(&amp;regs, setter), nil;799<a id="L801"></a>}800<a id="L803"></a>func (t *thread) Peek(addr Word, out []byte) (int, os.Error) {801 <a id="L804"></a>var c int;802 <a id="L806"></a>err := t.proc.do(func() os.Error {803 <a id="L807"></a>if !t.state.isStopped() {804 <a id="L808"></a>return &amp;badState{t, &#34;cannot peek text&#34;, t.state}805 <a id="L809"></a>}806 <a id="L811"></a>var err os.Error;807 <a id="L812"></a>c, err = t.ptracePeekText(uintptr(addr), out);808 <a id="L813"></a>return err;809 <a id="L814"></a>});810 <a id="L816"></a>return c, err;811<a id="L817"></a>}812<a id="L819"></a>func (t *thread) Poke(addr Word, out []byte) (int, os.Error) {813 <a id="L820"></a>var c int;814 <a id="L822"></a>err := t.proc.do(func() os.Error {815 <a id="L823"></a>if !t.state.isStopped() {816 <a id="L824"></a>return &amp;badState{t, &#34;cannot poke text&#34;, t.state}817 <a id="L825"></a>}818 <a id="L827"></a>var err os.Error;819 <a id="L828"></a>c, err = t.ptracePokeText(uintptr(addr), out);820 <a id="L829"></a>return err;821 <a id="L830"></a>});822 <a id="L832"></a>return c, err;823<a id="L833"></a>}824<a id="L835"></a><span class="comment">// stepAsync starts this thread single stepping. When the single step</span>825<a id="L836"></a><span class="comment">// is complete, it will send nil on the given channel. If an error</span>826<a id="L837"></a><span class="comment">// occurs while setting up the single step, it returns that error. If</span>827<a id="L838"></a><span class="comment">// an error occurs while waiting for the single step to complete, it</span>828<a id="L839"></a><span class="comment">// sends that error on the channel.</span>829<a id="L840"></a>func (t *thread) stepAsync(ready chan os.Error) os.Error {830 <a id="L841"></a>if err := t.ptraceStep(); err != nil {831 <a id="L842"></a>return err832 <a id="L843"></a>}833 <a id="L844"></a>t.setState(singleStepping);834 <a id="L845"></a>t.onStop(func() { ready &lt;- nil },835 <a id="L846"></a>func(err os.Error) { ready &lt;- err });836 <a id="L847"></a>return nil;837<a id="L848"></a>}838<a id="L850"></a>func (t *thread) Step() os.Error {839 <a id="L851"></a>t.logTrace(&#34;Step {&#34;);840 <a id="L852"></a>defer t.logTrace(&#34;}&#34;);841 <a id="L854"></a>ready := make(chan os.Error);842 <a id="L856"></a>err := t.proc.do(func() os.Error {843 <a id="L857"></a>if !t.state.isStopped() {844 <a id="L858"></a>return &amp;badState{t, &#34;cannot single step&#34;, t.state}845 <a id="L859"></a>}846 <a id="L860"></a>return t.stepAsync(ready);847 <a id="L861"></a>});848 <a id="L862"></a>if err != nil {849 <a id="L863"></a>return err850 <a id="L864"></a>}851 <a id="L866"></a>err = &lt;-ready;852 <a id="L867"></a>return err;853<a id="L868"></a>}854<a id="L870"></a><span class="comment">// TODO(austin) We should probably get this via C&#39;s strsignal.</span>855<a id="L871"></a>var sigNames = [...]string{856 <a id="L872"></a>&#34;SIGEXIT&#34;, &#34;SIGHUP&#34;, &#34;SIGINT&#34;, &#34;SIGQUIT&#34;, &#34;SIGILL&#34;,857 <a id="L873"></a>&#34;SIGTRAP&#34;, &#34;SIGABRT&#34;, &#34;SIGBUS&#34;, &#34;SIGFPE&#34;, &#34;SIGKILL&#34;,858 <a id="L874"></a>&#34;SIGUSR1&#34;, &#34;SIGSEGV&#34;, &#34;SIGUSR2&#34;, &#34;SIGPIPE&#34;, &#34;SIGALRM&#34;,859 <a id="L875"></a>&#34;SIGTERM&#34;, &#34;SIGSTKFLT&#34;, &#34;SIGCHLD&#34;, &#34;SIGCONT&#34;, &#34;SIGSTOP&#34;,860 <a id="L876"></a>&#34;SIGTSTP&#34;, &#34;SIGTTIN&#34;, &#34;SIGTTOU&#34;, &#34;SIGURG&#34;, &#34;SIGXCPU&#34;,861 <a id="L877"></a>&#34;SIGXFSZ&#34;, &#34;SIGVTALRM&#34;, &#34;SIGPROF&#34;, &#34;SIGWINCH&#34;, &#34;SIGPOLL&#34;,862 <a id="L878"></a>&#34;SIGPWR&#34;, &#34;SIGSYS&#34;,863<a id="L879"></a>}864<a id="L881"></a><span class="comment">// sigName returns the symbolic name for the given signal number. If</span>865<a id="L882"></a><span class="comment">// the signal number is invalid, returns &#34;&lt;invalid&gt;&#34;.</span>866<a id="L883"></a>func sigName(signal int) string {867 <a id="L884"></a>if signal &lt; 0 || signal &gt;= len(sigNames) {868 <a id="L885"></a>return &#34;&lt;invalid&gt;&#34;869 <a id="L886"></a>}870 <a id="L887"></a>return sigNames[signal];871<a id="L888"></a>}872<a id="L890"></a>func (t *thread) Stopped() (Cause, os.Error) {873 <a id="L891"></a>var c Cause;874 <a id="L892"></a>err := t.proc.do(func() os.Error {875 <a id="L893"></a>switch t.state {876 <a id="L894"></a>case stopped:877 <a id="L895"></a>c = Stopped{}878 <a id="L897"></a>case stoppedBreakpoint:879 <a id="L898"></a>c = Breakpoint(t.breakpoint.pc)880 <a id="L900"></a>case stoppedSignal:881 <a id="L901"></a>c = Signal(sigName(t.signal))882 <a id="L903"></a>case stoppedThreadCreate:883 <a id="L904"></a>c = &amp;ThreadCreate{t.newThread}884 <a id="L906"></a>case stoppedExiting, exiting, exited:885 <a id="L907"></a>if t.signal == -1 {886 <a id="L908"></a>c = &amp;ThreadExit{t.exitStatus, &#34;&#34;}887 <a id="L909"></a>} else {888 <a id="L910"></a>c = &amp;ThreadExit{t.exitStatus, sigName(t.signal)}889 <a id="L911"></a>}890 <a id="L913"></a>default:891 <a id="L914"></a>return &amp;badState{t, &#34;cannot get stop cause&#34;, t.state}892 <a id="L915"></a>}893 <a id="L916"></a>return nil;894 <a id="L917"></a>});895 <a id="L918"></a>if err != nil {896 <a id="L919"></a>return nil, err897 <a id="L920"></a>}898 <a id="L922"></a>return c, nil;899<a id="L923"></a>}900<a id="L925"></a>func (p *process) Threads() []Thread {901 <a id="L926"></a>var res []Thread;902 <a id="L928"></a>p.do(func() os.Error {903 <a id="L929"></a>res = make([]Thread, len(p.threads));904 <a id="L930"></a>i := 0;905 <a id="L931"></a>for _, t := range p.threads {906 <a id="L932"></a><span class="comment">// Exclude zombie threads.</span>907 <a id="L933"></a>st := t.state;908 <a id="L934"></a>if st == exiting || st == exited || st == detached {909 <a id="L935"></a>continue910 <a id="L936"></a>}911 <a id="L938"></a>res[i] = t;912 <a id="L939"></a>i++;913 <a id="L940"></a>}914 <a id="L941"></a>res = res[0:i];915 <a id="L942"></a>return nil;916 <a id="L943"></a>});917 <a id="L944"></a>return res;918<a id="L945"></a>}919<a id="L947"></a>func (p *process) AddBreakpoint(pc Word) os.Error {920 <a id="L948"></a>return p.do(func() os.Error {921 <a id="L949"></a>if t := p.someRunningThread(); t != nil {922 <a id="L950"></a>return &amp;badState{t, &#34;cannot add breakpoint&#34;, t.state}923 <a id="L951"></a>}924 <a id="L952"></a>if _, ok := p.breakpoints[uintptr(pc)]; ok {925 <a id="L953"></a>return breakpointExistsError(pc)926 <a id="L954"></a>}927 <a id="L955"></a>p.breakpoints[uintptr(pc)] = &amp;breakpoint{pc: uintptr(pc)};928 <a id="L956"></a>return nil;929 <a id="L957"></a>})930<a id="L958"></a>}931<a id="L960"></a>func (p *process) RemoveBreakpoint(pc Word) os.Error {932 <a id="L961"></a>return p.do(func() os.Error {933 <a id="L962"></a>if t := p.someRunningThread(); t != nil {934 <a id="L963"></a>return &amp;badState{t, &#34;cannot remove breakpoint&#34;, t.state}935 <a id="L964"></a>}936 <a id="L965"></a>if _, ok := p.breakpoints[uintptr(pc)]; !ok {937 <a id="L966"></a>return noBreakpointError(pc)938 <a id="L967"></a>}939 <a id="L968"></a>p.breakpoints[uintptr(pc)] = nil, false;940 <a id="L969"></a>return nil;941 <a id="L970"></a>})942<a id="L971"></a>}943<a id="L973"></a>func (p *process) Continue() os.Error {944 <a id="L974"></a><span class="comment">// Single step any threads that are stopped at breakpoints so</span>945 <a id="L975"></a><span class="comment">// we can reinstall breakpoints.</span>946 <a id="L976"></a>var ready chan os.Error;947 <a id="L977"></a>count := 0;948 <a id="L979"></a>err := p.do(func() os.Error {949 <a id="L980"></a><span class="comment">// We make the ready channel big enough to hold all</span>950 <a id="L981"></a><span class="comment">// ready message so we don&#39;t jam up the monitor if we</span>951 <a id="L982"></a><span class="comment">// stop listening (e.g., if there&#39;s an error).</span>952 <a id="L983"></a>ready = make(chan os.Error, len(p.threads));953 <a id="L985"></a>for _, t := range p.threads {954 <a id="L986"></a>if !t.state.isStopped() {955 <a id="L987"></a>continue956 <a id="L988"></a>}957 <a id="L990"></a><span class="comment">// We use the breakpoint map directly here</span>958 <a id="L991"></a><span class="comment">// instead of checking the stop cause because</span>959 <a id="L992"></a><span class="comment">// it could have been stopped at a breakpoint</span>960 <a id="L993"></a><span class="comment">// for some other reason, or the breakpoint</span>961 <a id="L994"></a><span class="comment">// could have been added since it was stopped.</span>962 <a id="L995"></a>var regs syscall.PtraceRegs;963 <a id="L996"></a>err := t.ptraceGetRegs(&amp;regs);964 <a id="L997"></a>if err != nil {965 <a id="L998"></a>return err966 <a id="L999"></a>}967 <a id="L1000"></a>if b, ok := p.breakpoints[uintptr(regs.PC())]; ok {968 <a id="L1001"></a>t.logTrace(&#34;stepping over breakpoint %v&#34;, b);969 <a id="L1002"></a>if err := t.stepAsync(ready); err != nil {970 <a id="L1003"></a>return err971 <a id="L1004"></a>}972 <a id="L1005"></a>count++;973 <a id="L1006"></a>}974 <a id="L1007"></a>}975 <a id="L1008"></a>return nil;976 <a id="L1009"></a>});977 <a id="L1010"></a>if err != nil {978 <a id="L1011"></a>p.stopMonitor(err);979 <a id="L1012"></a>return err;980 <a id="L1013"></a>}981 <a id="L1015"></a><span class="comment">// Wait for single stepping threads</span>982 <a id="L1016"></a>for count &gt; 0 {983 <a id="L1017"></a>err = &lt;-ready;984 <a id="L1018"></a>if err != nil {985 <a id="L1019"></a>p.stopMonitor(err);986 <a id="L1020"></a>return err;987 <a id="L1021"></a>}988 <a id="L1022"></a>count--;989 <a id="L1023"></a>}990 <a id="L1025"></a><span class="comment">// Continue all threads</span>991 <a id="L1026"></a>err = p.do(func() os.Error {992 <a id="L1027"></a>if err := p.installBreakpoints(); err != nil {993 <a id="L1028"></a>return err994 <a id="L1029"></a>}995 <a id="L1031"></a>for _, t := range p.threads {996 <a id="L1032"></a>var err os.Error;997 <a id="L1033"></a>switch {998 <a id="L1034"></a>case !t.state.isStopped():999 <a id="L1035"></a>continue1000 <a id="L1037"></a>case t.state == stoppedSignal &amp;&amp; t.signal != syscall.SIGSTOP &amp;&amp; t.signal != syscall.SIGTRAP:1001 <a id="L1038"></a>t.logTrace(&#34;continuing with signal %d&#34;, t.signal);1002 <a id="L1039"></a>err = t.ptraceContWithSignal(t.signal);1003 <a id="L1041"></a>default:1004 <a id="L1042"></a>t.logTrace(&#34;continuing&#34;);1005 <a id="L1043"></a>err = t.ptraceCont();1006 <a id="L1044"></a>}1007 <a id="L1045"></a>if err != nil {1008 <a id="L1046"></a>return err1009 <a id="L1047"></a>}1010 <a id="L1048"></a>if t.state == stoppedExiting {1011 <a id="L1049"></a>t.setState(exiting)1012 <a id="L1050"></a>} else {1013 <a id="L1051"></a>t.setState(running)1014 <a id="L1052"></a>}1015 <a id="L1053"></a>}1016 <a id="L1054"></a>return nil;1017 <a id="L1055"></a>});1018 <a id="L1056"></a>if err != nil {1019 <a id="L1057"></a><span class="comment">// TODO(austin) Do we need to stop the monitor with</span>1020 <a id="L1058"></a><span class="comment">// this error atomically with the do-routine above?</span>1021 <a id="L1059"></a>p.stopMonitor(err);1022 <a id="L1060"></a>return err;1023 <a id="L1061"></a>}1024 <a id="L1063"></a>return nil;1025<a id="L1064"></a>}1026<a id="L1066"></a>func (p *process) WaitStop() os.Error {1027 <a id="L1067"></a><span class="comment">// We need a non-blocking ready channel for the case where all</span>1028 <a id="L1068"></a><span class="comment">// threads are already stopped.</span>1029 <a id="L1069"></a>ready := make(chan os.Error, 1);1030 <a id="L1071"></a>err := p.do(func() os.Error {1031 <a id="L1072"></a><span class="comment">// Are all of the threads already stopped?</span>1032 <a id="L1073"></a>if p.someRunningThread() == nil {1033 <a id="L1074"></a>ready &lt;- nil;1034 <a id="L1075"></a>return nil;1035 <a id="L1076"></a>}1036 <a id="L1078"></a><span class="comment">// Monitor state transitions</span>1037 <a id="L1079"></a>h := &amp;transitionHandler{};1038 <a id="L1080"></a>h.handle = func(st *thread, old, new threadState) {1039 <a id="L1081"></a>if !new.isRunning() {1040 <a id="L1082"></a>if p.someRunningThread() == nil {1041 <a id="L1083"></a>ready &lt;- nil;1042 <a id="L1084"></a>return;1043 <a id="L1085"></a>}1044 <a id="L1086"></a>}1045 <a id="L1087"></a>p.transitionHandlers.Push(h);1046 <a id="L1088"></a>};1047 <a id="L1089"></a>h.onErr = func(err os.Error) { ready &lt;- err };1048 <a id="L1090"></a>p.transitionHandlers.Push(h);1049 <a id="L1091"></a>return nil;1050 <a id="L1092"></a>});1051 <a id="L1093"></a>if err != nil {1052 <a id="L1094"></a>return err1053 <a id="L1095"></a>}1054 <a id="L1097"></a>return &lt;-ready;1055<a id="L1098"></a>}1056<a id="L1100"></a>func (p *process) Stop() os.Error {1057 <a id="L1101"></a>err := p.do(func() os.Error { return p.stopAsync() });1058 <a id="L1102"></a>if err != nil {1059 <a id="L1103"></a>return err1060 <a id="L1104"></a>}1061 <a id="L1106"></a>return p.WaitStop();1062<a id="L1107"></a>}1063<a id="L1109"></a>func (p *process) Detach() os.Error {1064 <a id="L1110"></a>if err := p.Stop(); err != nil {1065 <a id="L1111"></a>return err1066 <a id="L1112"></a>}1067 <a id="L1114"></a>err := p.do(func() os.Error {1068 <a id="L1115"></a>if err := p.uninstallBreakpoints(); err != nil {1069 <a id="L1116"></a>return err1070 <a id="L1117"></a>}1071 <a id="L1119"></a>for pid, t := range p.threads {1072 <a id="L1120"></a>if t.state.isStopped() {1073 <a id="L1121"></a><span class="comment">// We can&#39;t detach from zombies.</span>1074 <a id="L1122"></a>if err := t.ptraceDetach(); err != nil {1075 <a id="L1123"></a>return err1076 <a id="L1124"></a>}1077 <a id="L1125"></a>}1078 <a id="L1126"></a>t.setState(detached);1079 <a id="L1127"></a>p.threads[pid] = nil, false;1080 <a id="L1128"></a>}1081 <a id="L1129"></a>return nil;1082 <a id="L1130"></a>});1083 <a id="L1131"></a><span class="comment">// TODO(austin) Wait for monitor thread to exit?</span>1084 <a id="L1132"></a>return err;1085<a id="L1133"></a>}1086<a id="L1135"></a><span class="comment">// newThread creates a new thread object and waits for its initial</span>1087<a id="L1136"></a><span class="comment">// signal. If cloned is true, this thread was cloned from a thread we</span>1088<a id="L1137"></a><span class="comment">// are already attached to.</span>1089<a id="L1138"></a><span class="comment">//</span>1090<a id="L1139"></a><span class="comment">// Must be run from the monitor thread.</span>1091<a id="L1140"></a>func (p *process) newThread(tid int, signal int, cloned bool) (*thread, os.Error) {1092 <a id="L1141"></a>t := &amp;thread{tid: tid, proc: p, state: stopped};1093 <a id="L1143"></a><span class="comment">// Get the signal from the thread</span>1094 <a id="L1144"></a><span class="comment">// TODO(austin) Thread might already be stopped if we&#39;re attaching.</span>1095 <a id="L1145"></a>w, err := os.Wait(tid, syscall.WALL);1096 <a id="L1146"></a>if err != nil {1097 <a id="L1147"></a>return nil, err1098 <a id="L1148"></a>}1099 <a id="L1149"></a>if w.Pid != tid || w.StopSignal() != signal {1100 <a id="L1150"></a>return nil, &amp;newThreadError{w, tid, signal}1101 <a id="L1151"></a>}1102 <a id="L1153"></a>if !cloned {1103 <a id="L1154"></a>err = t.ptraceSetOptions(syscall.PTRACE_O_TRACECLONE | syscall.PTRACE_O_TRACEEXIT);1104 <a id="L1155"></a>if err != nil {1105 <a id="L1156"></a>return nil, err1106 <a id="L1157"></a>}1107 <a id="L1158"></a>}1108 <a id="L1160"></a>p.threads[tid] = t;1109 <a id="L1162"></a>return t, nil;1110<a id="L1163"></a>}1111<a id="L1165"></a><span class="comment">// attachThread attaches a running thread to the process.</span>1112<a id="L1166"></a><span class="comment">//</span>1113<a id="L1167"></a><span class="comment">// Must NOT be run from the monitor thread.</span>1114<a id="L1168"></a>func (p *process) attachThread(tid int) (*thread, os.Error) {1115 <a id="L1169"></a>p.logTrace(&#34;attaching to thread %d&#34;, tid);1116 <a id="L1170"></a>var thr *thread;1117 <a id="L1171"></a>err := p.do(func() os.Error {1118 <a id="L1172"></a>errno := syscall.PtraceAttach(tid);1119 <a id="L1173"></a>if errno != 0 {1120 <a id="L1174"></a>return os.NewSyscallError(&#34;ptrace(ATTACH)&#34;, errno)1121 <a id="L1175"></a>}1122 <a id="L1177"></a>var err os.Error;1123 <a id="L1178"></a>thr, err = p.newThread(tid, syscall.SIGSTOP, false);1124 <a id="L1179"></a>return err;1125 <a id="L1180"></a>});1126 <a id="L1181"></a>return thr, err;1127<a id="L1182"></a>}1128<a id="L1184"></a><span class="comment">// attachAllThreads attaches to all threads in a process.</span>1129<a id="L1185"></a>func (p *process) attachAllThreads() os.Error {1130 <a id="L1186"></a>taskPath := &#34;/proc/&#34; + strconv.Itoa(p.pid) + &#34;/task&#34;;1131 <a id="L1187"></a>taskDir, err := os.Open(taskPath, os.O_RDONLY, 0);1132 <a id="L1188"></a>if err != nil {1133 <a id="L1189"></a>return err1134 <a id="L1190"></a>}1135 <a id="L1191"></a>defer taskDir.Close();1136 <a id="L1193"></a><span class="comment">// We stop threads as we attach to them; however, because new</span>1137 <a id="L1194"></a><span class="comment">// threads can appear while we&#39;re looping over all of them, we</span>1138 <a id="L1195"></a><span class="comment">// have to repeatly scan until we know we&#39;re attached to all</span>1139 <a id="L1196"></a><span class="comment">// of them.</span>1140 <a id="L1197"></a>for again := true; again; {1141 <a id="L1198"></a>again = false;1142 <a id="L1200"></a>tids, err := taskDir.Readdirnames(-1);1143 <a id="L1201"></a>if err != nil {1144 <a id="L1202"></a>return err1145 <a id="L1203"></a>}1146 <a id="L1205"></a>for _, tidStr := range tids {1147 <a id="L1206"></a>tid, err := strconv.Atoi(tidStr);1148 <a id="L1207"></a>if err != nil {1149 <a id="L1208"></a>return err1150 <a id="L1209"></a>}1151 <a id="L1210"></a>if _, ok := p.threads[tid]; ok {1152 <a id="L1211"></a>continue1153 <a id="L1212"></a>}1154 <a id="L1214"></a>_, err = p.attachThread(tid);1155 <a id="L1215"></a>if err != nil {1156 <a id="L1216"></a><span class="comment">// There could have been a race, or</span>1157 <a id="L1217"></a><span class="comment">// this process could be a zobmie.</span>1158 <a id="L1218"></a>statFile, err2 := io.ReadFile(taskPath + &#34;/&#34; + tidStr + &#34;/stat&#34;);1159 <a id="L1219"></a>if err2 != nil {1160 <a id="L1220"></a>switch err2 := err2.(type) {1161 <a id="L1221"></a>case *os.PathError:1162 <a id="L1222"></a>if err2.Error == os.ENOENT {1163 <a id="L1223"></a><span class="comment">// Raced with thread exit</span>1164 <a id="L1224"></a>p.logTrace(&#34;raced with thread %d exit&#34;, tid);1165 <a id="L1225"></a>continue;1166 <a id="L1226"></a>}1167 <a id="L1227"></a>}1168 <a id="L1228"></a><span class="comment">// Return the original error</span>1169 <a id="L1229"></a>return err;1170 <a id="L1230"></a>}1171 <a id="L1232"></a>statParts := strings.Split(string(statFile), &#34; &#34;, 4);1172 <a id="L1233"></a>if len(statParts) &gt; 2 &amp;&amp; statParts[2] == &#34;Z&#34; {1173 <a id="L1234"></a><span class="comment">// tid is a zombie</span>1174 <a id="L1235"></a>p.logTrace(&#34;thread %d is a zombie&#34;, tid);1175 <a id="L1236"></a>continue;1176 <a id="L1237"></a>}1177 <a id="L1239"></a><span class="comment">// Return the original error</span>1178 <a id="L1240"></a>return err;1179 <a id="L1241"></a>}1180 <a id="L1242"></a>again = true;1181 <a id="L1243"></a>}1182 <a id="L1244"></a>}1183 <a id="L1246"></a>return nil;1184<a id="L1247"></a>}1185<a id="L1249"></a><span class="comment">// newProcess creates a new process object and starts its monitor thread.</span>1186<a id="L1250"></a>func newProcess(pid int) *process {1187 <a id="L1251"></a>p := &amp;process{1188 <a id="L1252"></a>pid: pid,1189 <a id="L1253"></a>threads: make(map[int]*thread),1190 <a id="L1254"></a>breakpoints: make(map[uintptr]*breakpoint),1191 <a id="L1255"></a>ready: make(chan bool, 1),1192 <a id="L1256"></a>debugEvents: make(chan *debugEvent),1193 <a id="L1257"></a>debugReqs: make(chan *debugReq),1194 <a id="L1258"></a>stopReq: make(chan os.Error),1195 <a id="L1259"></a>transitionHandlers: vector.New(0),1196 <a id="L1260"></a>};1197 <a id="L1262"></a>go p.monitor();1198 <a id="L1264"></a>return p;1199<a id="L1265"></a>}1200<a id="L1267"></a><span class="comment">// Attach attaches to process pid and stops all of its threads.</span>1201<a id="L1268"></a>func Attach(pid int) (Process, os.Error) {1202 <a id="L1269"></a>p := newProcess(pid);1203 <a id="L1271"></a><span class="comment">// Attach to all threads</span>1204 <a id="L1272"></a>err := p.attachAllThreads();1205 <a id="L1273"></a>if err != nil {1206 <a id="L1274"></a>p.Detach();1207 <a id="L1275"></a><span class="comment">// TODO(austin) Detach stopped the monitor already</span>1208 <a id="L1276"></a><span class="comment">//p.stopMonitor(err);</span>1209 <a id="L1277"></a>return nil, err;1210 <a id="L1278"></a>}1211 <a id="L1280"></a>return p, nil;1212<a id="L1281"></a>}1213<a id="L1283"></a><span class="comment">// ForkExec forks the current process and execs argv0, stopping the</span>1214<a id="L1284"></a><span class="comment">// new process after the exec syscall. See os.ForkExec for additional</span>1215<a id="L1285"></a><span class="comment">// details.</span>1216<a id="L1286"></a>func ForkExec(argv0 string, argv []string, envv []string, dir string, fd []*os.File) (Process, os.Error) {1217 <a id="L1287"></a>p := newProcess(-1);1218 <a id="L1289"></a><span class="comment">// Create array of integer (system) fds.</span>1219 <a id="L1290"></a>intfd := make([]int, len(fd));1220 <a id="L1291"></a>for i, f := range fd {1221 <a id="L1292"></a>if f == nil {1222 <a id="L1293"></a>intfd[i] = -11223 <a id="L1294"></a>} else {1224 <a id="L1295"></a>intfd[i] = f.Fd()1225 <a id="L1296"></a>}1226 <a id="L1297"></a>}1227 <a id="L1299"></a><span class="comment">// Fork from the monitor thread so we get the right tracer pid.</span>1228 <a id="L1300"></a>err := p.do(func() os.Error {1229 <a id="L1301"></a>pid, errno := syscall.PtraceForkExec(argv0, argv, envv, dir, intfd);1230 <a id="L1302"></a>if errno != 0 {1231 <a id="L1303"></a>return &amp;os.PathError{&#34;fork/exec&#34;, argv0, os.Errno(errno)}1232 <a id="L1304"></a>}1233 <a id="L1305"></a>p.pid = pid;1234 <a id="L1307"></a><span class="comment">// The process will raise SIGTRAP when it reaches execve.</span>1235 <a id="L1308"></a>_, err := p.newThread(pid, syscall.SIGTRAP, false);1236 <a id="L1309"></a>return err;1237 <a id="L1310"></a>});1238 <a id="L1311"></a>if err != nil {1239 <a id="L1312"></a>p.stopMonitor(err);1240 <a id="L1313"></a>return nil, err;1241 <a id="L1314"></a>}1242 <a id="L1316"></a>return p, nil;1243<a id="L1317"></a>}1244</pre>1245</div>1246<div id="footer">1247<p>Except as noted, this content is1248 licensed under <a href="http://creativecommons.org/licenses/by/3.0/">1249 Creative Commons Attribution 3.0</a>.1250</div>1251<script type="text/javascript">1252var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");1253document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));1254</script>1255<script type="text/javascript">1256var pageTracker = _gat._getTracker("UA-11222381-2");1257pageTracker._trackPageview();1258</script>1259</body>1260</html>1261<!-- generated at Thu Nov 12 15:42:51 PST 2009 -->...

Full Screen

Full Screen

template.go

Source:template.go Github

copy

Full Screen

...55 return t, nil56 }57 tempPath := strings.Replace(name, "/", string(filepath.Separator), -1)58 tempFile := filepath.Join(webConfig.TemplateDir, tempPath)59 log.LogTrace("Parsing template %v", tempFile)60 var err error61 var t *template.Template62 if partial {63 // Need to get basename of file to make it root template w/ funcs64 base := path.Base(name)65 t = template.New(base).Funcs(TemplateFuncs)66 t, err = t.ParseFiles(tempFile)67 } else {68 t = template.New("layout.html").Funcs(TemplateFuncs)69 // Note that the layout file must be the first parameter in ParseFiles70 t, err = t.ParseFiles(filepath.Join(webConfig.TemplateDir, "layout.html"), tempFile)71 }72 if err != nil {73 return nil, err74 }75 // Allows us to disable caching for theme development76 if webConfig.TemplateCache {77 if partial {78 log.LogTrace("Caching partial %v", name)79 cachedTemplates[name] = t80 } else {81 log.LogTrace("Caching template %v", name)82 cachedTemplates[name] = t83 }84 }85 return t, nil86}87// HTML rendering88func htmlSafe(text string) template.HTML {89 p := bluemonday.UGCPolicy()90 txt := p.Sanitize(text)91 return template.HTML(txt)92}93// Friendly date & time rendering94func friendlyTime(t time.Time) template.HTML {95 ty, tm, td := t.Date()...

Full Screen

Full Screen

rpcxwrap.go

Source:rpcxwrap.go Github

copy

Full Screen

1package rpcxutil2import (3 "context"4 "time"5 "github.com/smallnest/rpcx/client"6 "github.com/smallnest/rpcx/share"7 "github.com/spf13/cast"8 logger "github.com/tal-tech/loggerX"9 "github.com/tal-tech/loggerX/logtrace"10 "github.com/tal-tech/xtools/traceutil"11)12const (13 DefaultWrapType = iota14 //------上下文key标识15 //超时时间, 值为time.duration 字符串,如:1s16 // 配置文件:rpcCallTimeout 为全局, 为单独请求设置17 WRAPCLIENT_CTX_KEY_CALLTIMEOUT = "WRAPCLIENT_CTX_KEY_CALLTIMEOUT"18)19type RpcxWrap interface {20 WrapCall(client.XClient, context.Context, string, interface{}, interface{}) error21}22type DefaultWrap struct {23 serviceName string24}25func NewDefaultWrap(serviceName string) RpcxWrap {26 w := new(DefaultWrap)27 w.serviceName = serviceName28 return w29}30func (d *DefaultWrap) WrapCall(c client.XClient, ctx context.Context, serviceMethod string, args interface{}, reply interface{}) (err error) {31 tag := d.serviceName + "." + serviceMethod32 logger.Tx(ctx, tag, "Trace Rpc Call [destinationAddr:%s]", d.getServerAddr(ctx))33 if skip := ctx.Value("RPCXSKIPLOG"); skip == nil {34 defer func() {35 logger.Ix(ctx, tag, "[destinationAddr:%s], WrapCall args:[%+v],reply:[%+v]", d.getServerAddr(ctx), args, reply)36 }()37 }38 metadata := map[string]string{39 "logid": cast.ToString(ctx.Value("logid")),40 "hostname": cast.ToString(ctx.Value("hostname")),41 "IS_PLAYBACK": cast.ToString(ctx.Value("IS_PLAYBACK")),42 "IS_BENCHMARK": cast.ToString(ctx.Value("IS_BENCHMARK")),43 "url": cast.ToString(ctx.Value("url")),44 }45 if cast.ToString(ctx.Value("extra")) != "" {46 metadata["extra"] = cast.ToString(ctx.Value("extra"))47 }48 if appId != "" {49 timestamp, sign := genRpcAuth()50 metadata["X-Auth-TimeStamp"] = timestamp51 metadata["X-Auth-Sign"] = sign52 }53 if cast.ToString(ctx.Value("RPCX_APPID")) != "" {54 metadata["X-Auth-AppId"] = cast.ToString(ctx.Value("RPCX_APPID"))55 metadata["X-Auth-TimeStamp"] = cast.ToString(ctx.Value("RPCX_TIMESTAMP"))56 metadata["X-Auth-Sign"] = cast.ToString(ctx.Value("RPCX_SIGN"))57 }58 ctx = context.WithValue(ctx, share.ReqMetaDataKey, metadata)59 span, ctx := traceutil.TraceRPCXInject(ctx, tag)60 if span != nil {61 defer span.Finish()62 }63 logtrace.InjectTraceNodeToRpcx(ctx)64 if rpcxOptCallTimeout > 0 {65 err = d.callWithTimeout(c, ctx, serviceMethod, args, reply)66 } else {67 err = c.Call(ctx, serviceMethod, args, reply)68 }69 return70}71//超时控制72func (d *DefaultWrap) callWithTimeout(c client.XClient, ctx context.Context, serviceMethod string, args interface{}, reply interface{}) error {73 timeout := rpcxOptCallTimeout74 if t := cast.ToString(ctx.Value(WRAPCLIENT_CTX_KEY_CALLTIMEOUT)); t != "" {75 if td, err := time.ParseDuration(t); err == nil && td > 0 {76 timeout = td77 }78 }79 ctx, cancel := context.WithTimeout(ctx, timeout)80 defer cancel()81 return c.Call(ctx, serviceMethod, args, reply)82}83func (d *DefaultWrap) getServerAddr(ctx context.Context) (serverAddr string) {84 if metaData := ctx.Value(share.ReqMetaDataKey); metaData != nil {85 m, ok := metaData.(map[string]string)86 if !ok {87 return88 }89 if addr, ok := m["DESTINATION_ADDR"]; ok {90 return addr91 }92 }93 return94}...

Full Screen

Full Screen

LogTrace

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 beego.BeeLogger.DelLogger("console")4 beego.BeeLogger.SetLogger(logs.AdapterFile, `{"filename":"test.log"}`)5 beego.BeeLogger.EnableFuncCallDepth(true)6 beego.BeeLogger.SetLogFuncCallDepth(3)7 beego.BeeLogger.Trace("trace")8 beego.BeeLogger.Debug("debug")9 beego.BeeLogger.Info("info")10 beego.BeeLogger.Warn("warn")11 beego.BeeLogger.Error("error")12 beego.BeeLogger.Critical("critical")13}14import (15func main() {16 beego.BeeLogger.DelLogger("console")17 beego.BeeLogger.SetLogger(logs.AdapterFile, `{"filename":"test.log"}`)18 beego.BeeLogger.EnableFuncCallDepth(true)19 beego.BeeLogger.SetLogFuncCallDepth(3)20 beego.BeeLogger.LogTrace("trace")21 beego.BeeLogger.LogDebug("debug")22 beego.BeeLogger.LogInfo("info")23 beego.BeeLogger.LogWarn("warn")24 beego.BeeLogger.LogError("error")25 beego.BeeLogger.LogCritical("critical")26}27import (28func main() {29 beego.BeeLogger.DelLogger("console")30 beego.BeeLogger.SetLogger(logs.AdapterFile, `{"filename":"test.log"}`)31 beego.BeeLogger.EnableFuncCallDepth(true)32 beego.BeeLogger.SetLogFuncCallDepth(3)33 beego.BeeLogger.Trace("trace")34 beego.BeeLogger.Debug("debug")35 beego.BeeLogger.Info("info")36 beego.BeeLogger.Warn("warn")37 beego.BeeLogger.Error("error")

Full Screen

Full Screen

LogTrace

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 td.LogTrace("Hello World")4}5import (6func main() {7 td.LogTrace("Hello World")8}9import (10func main() {11 td.LogTrace("Hello World")12}13import (14func main() {15 td.LogTrace("Hello World")16}17import (18func main() {19 td.LogTrace("Hello World")20}21import (22func main() {23 td.LogTrace("Hello World")24}25import (26func main() {27 td.LogTrace("Hello World")28}29import (30func main() {31 td.LogTrace("Hello World")32}33import (34func main() {35 td.LogTrace("Hello World")36}37import (38func main() {39 td.LogTrace("Hello World")40}

Full Screen

Full Screen

LogTrace

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 td.LogTrace("test")4}5import (6func main() {7 td.LogTrace("test")8}9import (10func main() {11 td.LogTrace("test")12}13import (14func main() {15 td.LogTrace("test")16}17import (18func main() {19 td.LogTrace("test")20}21import (22func main() {

Full Screen

Full Screen

LogTrace

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 fmt.Println("Hello World")4 td.LogTrace("Hello World")5}6import (7func main() {8 fmt.Println("Hello World")9 td.LogDebug("Hello World")10}11import (12func main() {13 fmt.Println("Hello World")14 td.LogInfo("Hello World")15}16import (17func main() {18 fmt.Println("Hello World")19 td.LogWarn("Hello World")20}21import (22func main() {23 fmt.Println("Hello World")24 td.LogError("Hello World")25}26import (27func main() {28 fmt.Println("Hello World")29 td.LogFatal("Hello World")30}31import (32func main() {33 fmt.Println("Hello World")34 td.LogPanic("Hello World")35}36import (37func main() {38 fmt.Println("Hello World")39 td.LogTracef("Hello %s", "World")40}

Full Screen

Full Screen

LogTrace

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 td.LogTrace("LogTrace called from 2.go")4 fmt.Println("2.go: Hello World")5}6import (7func main() {8 td.LogTrace("LogTrace called from 1.go")9 fmt.Println("1.go: Hello World")10}11import (12func main() {13 td.LogTrace("LogTrace called from 3.go")14 fmt.Println("3.go: Hello World")15}16import (17func main() {18 td.LogTrace("LogTrace called from 4.go")19 fmt.Println("4.go: Hello World")20}21import (22func main() {23 td.LogTrace("LogTrace called from 5.go")24 fmt.Println("5.go: Hello World")25}26import (27func main() {28 td.LogTrace("LogTrace called from 6.go")29 fmt.Println("6.go: Hello World")30}31import (32func main() {33 td.LogTrace("LogTrace called from 7.go")34 fmt.Println("7.go: Hello World")35}36import (37func main() {38 td.LogTrace("LogTrace called from 8.go")39 fmt.Println("8.go: Hello World")40}41import (42func main() {43 td.LogTrace("LogTrace called from 9.go")44 fmt.Println("9.go: Hello World")45}

Full Screen

Full Screen

LogTrace

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 td.LogTrace("Hello")4}5import (6func main() {7 td.LogDebug("Hello")8}9import (10func main() {11 td.LogInfo("Hello")12}13import (14func main() {15 td.LogWarn("Hello")16}17import (18func main() {19 td.LogError("Hello")20}21import (22func main() {23 td.LogFatal("Hello")24}

Full Screen

Full Screen

Automation Testing Tutorials

Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Run Go-testdeep automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Most used method in

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful