// Wait blocks until a thread/child process enters or exits a region. The wait
// status will be placed in the 'status' variable. The affected process will be
// returned. Since multiple regions may be affected (if two regions end on the
// same address), a list of events is returned indicating which regions were
// affected and whether they have been entered or exited by the process.
Wait blocks until a thread/child process enters or exits a region. The wait
status will be placed in the 'status' variable. The affected process will be
returned. Since multiple regions may be affected (if two regions end on the
same address), a list of events is returned indicating which regions were
affected and whether they have been entered or exited by the process.
// Wait blocks until a thread / child process enters or exits a region . The wait // status will be placed in the ' status ' variable . The affected process will be // returned . Since multiple regions may be affected ( if two regions end on the // same address ) a list of events is returned indicating which regions were // affected and whether they have been entered or exited by the process .
func (p *Program) Wait(status *Status) (*Proc, []Event, error) {
	ws := &status.WaitStatus
	wpid, err := unix.Wait4(-1, ws, 0, nil)
	if err != nil {
		return nil, nil, err
	}
	status.sig = 0
	status.groupStop = false
	untraced := false
	proc, ok := p.procs[wpid]
	if !ok {
		proc, untraced = p.untraced[wpid]
		if !untraced {
			proc, err = newTracedProc(wpid, p.pie, p.regions, p.breakpoints)
			if err != nil {
				return nil, nil, err
			}
			p.procs[wpid] = proc
			logger.Printf("%d: new process created (tracing enabled)\n", wpid)
			return proc, nil, nil
		}
	}
	if ws.Exited() || ws.Signaled() {
		logger.Printf("%d: exited\n", wpid)
		delete(p.procs, wpid)
		proc.exit()
		if len(p.procs) == 0 {
			return proc, nil, ErrFinishedTrace
		}
	} else if !ws.Stopped() {
		return proc, nil, nil
	} else if ws.StopSignal() != unix.SIGTRAP {
		if statusPtraceEventStop(*ws) {
			status.groupStop = true
			logger.Printf("%d: received group stop\n", wpid)
		} else {
			logger.Printf("%d: received signal '%s'\n", wpid, ws.StopSignal())
			status.sig = ws.StopSignal()
		}
	} else if ws.TrapCause() == unix.PTRACE_EVENT_CLONE {
		newpid, err := proc.tracer.GetEventMsg()
		logger.Printf("%d: called clone() = %d (err=%v)\n", wpid, newpid, err)
	} else if ws.TrapCause() == unix.PTRACE_EVENT_FORK {
		logger.Printf("%d: called fork()\n", wpid)
	} else if ws.TrapCause() == unix.PTRACE_EVENT_VFORK {
		logger.Printf("%d: called vfork()\n", wpid)
	} else if ws.TrapCause() == unix.PTRACE_EVENT_EXEC {
		logger.Printf("%d: called exec() (tracing disabled)\n", wpid)
		delete(p.procs, wpid)
		p.untraced[wpid] = proc
	} else if !untraced {
		events, err := proc.handleInterrupt()
		if err != nil {
			return nil, nil, err
		}
		return proc, events, nil
	}
	return proc, nil, nil
}
func ( p * Program ) Wait ( status * Status ) ( * Proc , [ ] Event , error ) { ws := & status . WaitStatus wpid , err := unix . Wait4 ( - 1 , ws , 0 , nil ) if err != nil { return nil , nil , err } status . sig = 0 status . groupStop = false untraced := false proc , ok := p . procs [ wpid ] if ! ok { proc , untraced = p . untraced [ wpid ] if ! untraced { proc , err = newTracedProc ( wpid , p . pie , p . regions , p . breakpoints ) if err != nil { return nil , nil , err } p . procs [ wpid ] = proc logger . Printf ( " \n " , wpid ) return proc , nil , nil } } if ws . Exited ( ) || ws . Signaled ( ) { logger . Printf ( " \n " , wpid ) delete ( p . procs , wpid ) proc . exit ( ) if len ( p . procs ) == 0 { return proc , nil , ErrFinishedTrace } } else if ! ws . Stopped ( ) { return proc , nil , nil } else if ws . StopSignal ( ) != unix . SIGTRAP { if statusPtraceEventStop ( * ws ) { status . groupStop = true logger . Printf ( " \n " , wpid ) } else { logger . Printf ( " \n " , wpid , ws . StopSignal ( ) ) status . sig = ws . StopSignal ( ) } } else if ws . TrapCause ( ) == unix . PTRACE_EVENT_CLONE { newpid , err := proc . tracer . GetEventMsg ( ) logger . Printf ( " \n " , wpid , newpid , err ) } else if ws . TrapCause ( ) == unix . PTRACE_EVENT_FORK { logger . Printf ( " \n " , wpid ) } else if ws . TrapCause ( ) == unix . PTRACE_EVENT_VFORK { logger . Printf ( " \n " , wpid ) } else if ws . TrapCause ( ) == unix . PTRACE_EVENT_EXEC { logger . Printf ( " \n " , wpid ) delete ( p . procs , wpid ) p . untraced [ wpid ] = proc } else if ! untraced { events , err := proc . handleInterrupt ( ) if err != nil { return nil , nil , err } return proc , events , nil } return proc , nil , nil }
Wait blocks until a thread/child process enters or exits a region.
Wait blocks until a thread / child process enters or exits a region .