def pause(self):
"""Pause the process by sending a SIGSTOP to the child
A limitation of the method is it will only pause the initial
child process created any further (grandchild) processes created
will not be paused.
This method is a no-op on Windows.
"""
try:
self.command_process.send_signal(signal.SIGSTOP)
except (ValueError, AttributeError, OSError):
pass
python类SIGSTOP的实例源码
def addProcess(self, pid, is_attached, parent=None, is_thread=False):
"""
Add a new process using its identifier. Use is_attached=False to
attach an existing (running) process, and is_attached=True to trace
a new (stopped) process.
"""
if pid in self.dict:
raise KeyError("The process %s is already registered!" % pid)
process = PtraceProcess(self, pid, is_attached,
parent=parent, is_thread=is_thread)
info("Attach %s to debugger" % process)
self.dict[pid] = process
self.list.append(process)
try:
process.waitSignals(SIGTRAP, SIGSTOP)
except KeyboardInterrupt:
error(
"User interrupt! Force the process %s attach "
"(don't wait for signals)."
% pid)
except ProcessSignal as event:
event.display()
except: # noqa: E722
process.is_attached = False
process.detach()
raise
if HAS_PTRACE_EVENTS and self.options:
process.setoptions(self.options)
return process
def signal(self, sig):
"""
Signal the process of an event.
"""
if sig == signal.SIGKILL:
self.kill()
elif sig == signal.SIGTERM:
self.terminate()
elif sig == signal.SIGSTOP:
self.pause()
elif sig == signal.SIGCONT:
self.unpause()
else:
self.on_signal(sig)
def pause(self):
"""
Pause the process, able to be continued later
"""
self.signal(signal.SIGSTOP)
def process_sh_cmd(self, cmd):
"""{SH_EXEC} [cmd [args ...] | {{fmt string}}]
Escape to {SHELL} or execute `cmd` in {SHELL}
- without arguments, the current interpreter will be suspended
and you will be dropped in a {SHELL} prompt. Use fg to return.
- with arguments, the text will be executed in {SHELL} and the
output/error will be displayed. Additionally '_' will contain
a named tuple with the (<stdout>, <stderror>, <return_code>)
for the execution of the command.
You may pass strings from the global namespace to the command
line using the `.format()` syntax. for example:
>>> filename = '/does/not/exist'
>>> !ls {{filename}}
ls: cannot access /does/not/exist: No such file or directory
>>> _
CmdExec(out='', err='ls: cannot access /does/not/exist: No such file or directory\n', rc=2)
"""
if cmd:
try:
cmd = cmd.format(**self.locals)
cmd = shlex.split(cmd)
if cmd[0] == 'cd':
os.chdir(os.path.expanduser(os.path.expandvars(' '.join(cmd[1:]) or '${HOME}')))
else:
cmd_exec = namedtuple('CmdExec', ['out', 'err', 'rc'])
process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = process.communicate()
rc = process.returncode
print (red(err.decode('utf-8')) if err else green(out.decode('utf-8'), bold=False))
builtins._ = cmd_exec(out, err, rc)
del cmd_exec
except:
self.showtraceback()
else:
if os.getenv('SSH_CONNECTION'):
# I use the bash function similar to the one below in my
# .bashrc to directly open a python prompt on remote
# systems I log on to.
# function rpython { ssh -t $1 -- "python" }
# Unfortunately, suspending this ssh session, does not place me
# in a shell, so I need to create one:
os.system(config['SHELL'])
else:
os.kill(os.getpid(), signal.SIGSTOP)
def run_tracee(tracee_binary):
'''
load tracee binary into memory.
return tracee pid
'''
# start tracee process and load tracee_binary into memory
pid = os.fork()
if pid == 0: # within tracee
# make tracee process tracable for tracer
pyptrace.traceme()
# stop and wake up tracer
os.kill(os.getpid(), signal.SIGSTOP)
# load tracee_binary
abs_tracee_binary_path = os.path.abspath(tracee_binary)
tracee_binary_name = os.path.basename(abs_tracee_binary_path)
ret = os.execv(abs_tracee_binary_path, [tracee_binary_name])
if ret:
raise Exception('execv failed, we were in bit trouble now')
elif pid > 0: # within tracer
# wait for tracee to set traceme
os.waitpid(pid, 0)
# set PTRACE_O_EXITKILL for tracee
pyptrace.setoptions(pid, pyptrace.PTRACE_O_EXITKILL)
# make tracee run execve
pyptrace.cont(pid)
# wait for execve of tracee to stop
os.waitpid(pid, 0)
# we've done our job
# tracee has been started and pause now
else:
# ignore
pass
return pid
def platformExec(self, cmdline):
# Very similar to posix, but not
# quite close enough...
self.execing = True
cmdlist = e_cli.splitargs(cmdline)
os.stat(cmdlist[0])
pid = os.fork()
if pid == 0:
try:
# Don't use PT_TRACEME -- on some linux (tested on ubuntu)
# it will cause immediate asignment of ptrace slot to parent
# without parent having PT_ATTACH'D.... MAKES SYNCHRONIZATION HARD
# SIGSTOP our self until parent continues us
os.kill(os.getpid(), signal.SIGSTOP)
os.execv(cmdlist[0], cmdlist)
except Exception as e:
print(e)
sys.exit(-1)
# Attach to child. should cause SIGSTOP
if 0 != v_posix.ptrace(PT_ATTACH, pid, 0, 0):
raise Exception("PT_ATTACH failed! linux platformExec")
# Eat all SIGSTOP (or other signal) and break from loop on SIGTRAP.
# SIGTRAP triggered by execv while PTRACE_ATTACH'd
while True:
wpid, status = os.waitpid(pid, os.WUNTRACED)
if wpid != pid: # should never happen
continue
if os.WIFSTOPPED(status):
cause = os.WSTOPSIG(status)
if cause == signal.SIGTRAP:
break
if v_posix.ptrace(v_posix.PT_CONTINUE, pid, 0, 0) != 0:
raise Exception("PT_CONTINUE failed! linux platformExec")
# Do a single step, which will allow a new stop event for the
# rest of vtrace to eat up.
if v_posix.ptrace(v_posix.PT_STEP, pid, 0, 0) != 0:
raise Exception("PT_CONTINUE failed! linux platformExec")
self.pthreads = [pid, ]
self.setMeta("ExeName", self._findExe(pid))
return pid