def waitExit(self):
debug("Wait %s exit" % self)
while True:
# Wait for any process signal
event = self.waitEvent()
event_cls = event.__class__
# Process exited: we are done
if event_cls == ProcessExit:
debug(str(event))
return
# Event different than a signal? Raise an exception
if event_cls != ProcessSignal:
raise event
# Send the signal to the process
signum = event.signum
if signum not in (SIGTRAP, SIGSTOP):
self.cont(signum)
else:
self.cont()
python类SIGSTOP的实例源码
def setup(self):
self.parse_processes()
for proc in self._processes.values():
if proc["pid"] == os.getpid():
continue
if any(proc["comm"].startswith(pref) for pref in self.misc_settings["comm_prefixes_ignored"]):
continue
if proc["nice"] == "-" or int(proc["nice"]) < self.misc_settings["min_nice"]:
continue
suffixes = self.misc_settings["subtree_suffixes"]
if any(proc["comm"].startswith(pref) for pref in self.misc_settings["comm_prefixes"]) or \
proc["pid"] >= self.misc_settings["min_id"] or \
any(any(pcomm.endswith(suff) for suff in suffixes) for pcomm in self._get_pcomms(proc["pid"])):
if self.misc_settings["dry_run"]:
logging.info(self._proc_dict_to_str(proc))
else:
self._pids.append(proc["pid"])
if self.misc_settings["dry_run"]:
raise KeyboardInterrupt()
self._send_signal(signal.SIGSTOP)
def platformWait(self):
# Blocking wait once...
pid, status = os.waitpid(-1, 0x40000002)
self.setMeta("ThreadId", pid)
# Stop the rest of the threads...
# why is linux debugging so Ghetto?!?!
if not self.stepping: # If we're stepping, only do the one
for tid in self.pthreads:
if tid == pid:
continue
try:
# We use SIGSTOP here because they can't mask it.
os.kill(tid, signal.SIGSTOP)
os.waitpid(tid, 0x40000002)
except Exception as e:
print("WARNING TID is invalid %d %s" % (tid, e))
return pid, status
def execute(self,dt):
if self.finished: return "finished"
if not self.running:
self.process = Process(target = executeInProcessGroup, args = (self,))
self.process.start()
print "timeshare child PID:",self.process.pid
os.setpgid(self.process.pid,self.process.pid)
print "timeshare process group",os.getpgid(self.process.pid)
assert os.getpgid(self.process.pid) == self.process.pid
print "my process group",os.getpgrp(),"which should be",os.getpgid(0)
assert os.getpgid(self.process.pid) != os.getpgid(0)
self.running = True
else:
os.killpg(self.process.pid, signal.SIGCONT)
self.process.join(dt)
if self.process.is_alive():
os.killpg(self.process.pid, signal.SIGSTOP)
return "still running"
else:
self.finished = True
return self.q.get()
def waitExit(self):
while True:
# Wait for any process signal
event = self.waitEvent()
event_cls = event.__class__
# Process exited: we are done
if event_cls == ProcessExit:
return
# Event different than a signal? Raise an exception
if event_cls != ProcessSignal:
raise event
# Send the signal to the process
signum = event.signum
if signum not in (SIGTRAP, SIGSTOP):
self.cont(signum)
else:
self.cont()
def addProcess(self, pid, is_attached, parent=None):
if pid in self.dict:
raise KeyError("Process % is already registered!" % pid)
process = PtraceProcess(self, pid, is_attached, parent=parent)
info("Attach %s to debugger" % process)
self.dict[pid] = process
self.list.append(process)
process.waitSignals(SIGTRAP, SIGSTOP)
if HAS_PTRACE_EVENTS and self.options:
process.setoptions(self.options)
return process
def do(self):
import signal
r = self.reader
p = r.pos
r.console.finish()
os.kill(os.getpid(), signal.SIGSTOP)
## this should probably be done
## in a handler for SIGCONT?
r.console.prepare()
r.pos = p
r.posxy = 0, 0
r.dirty = 1
r.console.screen = []
def suspend(self):
"""Suspend process execution with SIGSTOP pre-emptively checking
whether PID has been reused.
On Windows this has the effect ot suspending all process threads.
"""
if POSIX:
self._send_signal(signal.SIGSTOP)
else: # pragma: no cover
self._proc.suspend()
def suspend(self):
"""Suspend process execution with SIGSTOP pre-emptively checking
whether PID has been reused.
On Windows this has the effect ot suspending all process threads.
"""
if POSIX:
self._send_signal(signal.SIGSTOP)
else: # pragma: no cover
self._proc.suspend()
def suspend(self):
"""Suspend process execution with SIGSTOP pre-emptively checking
whether PID has been reused.
On Windows this has the effect ot suspending all process threads.
"""
if POSIX:
self._send_signal(signal.SIGSTOP)
else: # pragma: no cover
self._proc.suspend()
def suspend(self):
"""Suspend process execution with SIGSTOP pre-emptively checking
whether PID has been reused.
On Windows this has the effect ot suspending all process threads.
"""
if POSIX:
self._send_signal(signal.SIGSTOP)
else: # pragma: no cover
self._proc.suspend()
def test_kill_process_with_sigkill(self):
"""
Verify that killing process really works, even if something is
holding the process badly. In these cases, a SIGKILL is performed
some time after the SIGTERM was issued and didn't work.
"""
output_filename = self.makeFile("NOT RUN")
self._write_script(
("#!%s\n"
"import signal, os\n"
"signal.signal(signal.SIGTERM, signal.SIG_IGN)\n"
"file = open(%r, 'w')\n"
"file.write('RUN')\n"
"file.close()\n"
"os.kill(os.getpid(), signal.SIGSTOP)\n"
) % (sys.executable, output_filename))
self.addCleanup(setattr, landscape.client.watchdog, "SIGKILL_DELAY",
landscape.client.watchdog.SIGKILL_DELAY)
landscape.client.watchdog.SIGKILL_DELAY = 1
waiter = FileChangeWaiter(output_filename)
self.daemon.start()
waiter.wait()
self.assertEqual(open(output_filename).read(), "RUN")
return self.daemon.stop()
def test_wait_or_die_kills(self):
"""
wait_or_die eventually falls back to KILLing a process, after waiting
and terminating don't work.
"""
output_filename = self.makeFile("NOT RUN")
self._write_script(
("#!%s\n"
"import signal, os\n"
"signal.signal(signal.SIGTERM, signal.SIG_IGN)\n"
"file = open(%r, 'w')\n"
"file.write('RUN')\n"
"file.close()\n"
"os.kill(os.getpid(), signal.SIGSTOP)\n"
) % (sys.executable, output_filename))
self.addCleanup(setattr,
landscape.client.watchdog, "SIGKILL_DELAY",
landscape.client.watchdog.SIGKILL_DELAY)
self.addCleanup(setattr,
landscape.client.watchdog, "GRACEFUL_WAIT_PERIOD",
landscape.client.watchdog.GRACEFUL_WAIT_PERIOD)
landscape.client.watchdog.GRACEFUL_WAIT_PERIOD = 1
landscape.client.watchdog.SIGKILL_DELAY = 1
waiter = FileChangeWaiter(output_filename)
self.daemon.start()
waiter.wait()
self.assertEqual(open(output_filename).read(), "RUN")
return self.daemon.wait_or_die()
def suspend(self):
"""Suspend process execution with SIGSTOP pre-emptively checking
whether PID has been reused.
On Windows this has the effect ot suspending all process threads.
"""
if POSIX:
self._send_signal(signal.SIGSTOP)
else: # pragma: no cover
self._proc.suspend()
def handlePosixSignal(self, sig):
if sig == signal.SIGTRAP:
# FIXME I think we can catch these!
# Traps on posix systems are a little complicated
if self.stepping:
self.stepping = False
self.fireNotifiers(vtrace.NOTIFY_STEP)
# FIXME and these too...
elif self.checkBreakpoints():
# It was either a known BP or a sendBreak()
return
elif self.execing:
self.execing = False
self.handleAttach()
else:
self._fireSignal(sig)
elif sig == signal.SIGSTOP:
# We get a regular POSIX stop signal on attach
#self.attaching = False
self.handleAttach()
else:
self._fireSignal(sig)
def handlePosixSignal(self, sig):
"""
Handle a basic posix signal for this trace. This was seperated from
platformProcessEvent so extenders could skim events and still use this logic.
"""
if sig == signal.SIGTRAP:
# Traps on posix systems are a little complicated
if self.stepping:
# FIXME try out was single step thing for intel
self.stepping = False
self._fireStep()
elif self.checkWatchpoints():
return
elif self.checkBreakpoints():
# It was either a known BP or a sendBreak()
return
elif self.execing:
self.execing = False
self.handleAttach()
else:
self._fireSignal(sig)
elif sig == signal.SIGSTOP:
# FIXME only on attaching..
self.handleAttach()
else:
self._fireSignal(sig)
def handler_sigstop(signum, stack):
resetterm()
os.kill(os.getpid(), signal.SIGSTOP)
def freeze(self, nodes=None, sec=None):
if sec:
task = {'freeze': {'grep': self.grep, 'sec': sec}}
else:
task = {'kill': {'grep': self.grep, 'sig': signal.SIGSTOP}}
message = "Freeze %s" % (('for %s sec ' % sec) if sec else '')
self._run_task(nodes, task, message)
def run_master(mothership_url, workingdir, master_of):
with tempdir(workingdir, 'mothership_afl_master_') as directory:
logger.info('Starting master in %s' % (directory,))
master = MothershipMaster(mothership_url, directory, master_of)
os.makedirs(master.campaign_directory)
download_afl(mothership_url, directory)
download_queue(master.download_url, master.campaign_directory, [], executable_name=master.program)
master.start()
while not master.instance.process:
time.sleep(1)
global active
while not master.instance.process.poll():
#time.sleep(5 * 60)
time.sleep(10)
try:
campaign_active = requests.get(mothership_url + '/fuzzers/is_active/%d' % master_of).json()['active']
except Exception:
continue
if active != campaign_active:
if campaign_active:
logger.warn('Resuming master')
os.kill(master.instance.process.pid, signal.SIGCONT)
else:
logger.warn('Pausing master')
os.kill(master.instance.process.pid, signal.SIGSTOP)
active = campaign_active
master.join()
def do(self):
import signal
r = self.reader
p = r.pos
r.console.finish()
os.kill(os.getpid(), signal.SIGSTOP)
## this should probably be done
## in a handler for SIGCONT?
r.console.prepare()
r.pos = p
r.posxy = 0, 0
r.dirty = 1
r.console.screen = []
def suspend(self):
"""Suspend process execution with SIGSTOP pre-emptively checking
whether PID has been reused.
On Windows this has the effect ot suspending all process threads.
"""
if POSIX:
self._send_signal(signal.SIGSTOP)
else: # pragma: no cover
self._proc.suspend()
def suspend(self):
try:
# noinspection PyUnresolvedReferences
self._process.send_signal(signal.SIGSTOP)
except AttributeError:
logger.warning(
'SIGSTOP is not available on this platform'
)
def suspend(self):
"""Suspend process execution with SIGSTOP pre-emptively checking
whether PID has been reused.
On Windows this has the effect ot suspending all process threads.
"""
if _POSIX:
self._send_signal(signal.SIGSTOP)
else:
self._proc.suspend()
def suspend(self):
"""Suspend process execution with SIGSTOP pre-emptively checking
whether PID has been reused.
On Windows this has the effect ot suspending all process threads.
"""
if POSIX:
self._send_signal(signal.SIGSTOP)
else: # pragma: no cover
self._proc.suspend()
def suspend(self):
"""Suspend process execution with SIGSTOP pre-emptively checking
whether PID has been reused.
On Windows this has the effect ot suspending all process threads.
"""
if POSIX:
self._send_signal(signal.SIGSTOP)
else: # pragma: no cover
self._proc.suspend()
def test_suspend_doesnt_crash(self):
import os
import shutil
import signal
import subprocess
import sys
import tempfile
self.tempdir = tempfile.mkdtemp('test_suspend')
filename = os.path.join(self.tempdir, 'test_suspend.py')
fd = open(filename, "w")
fd.write("""import eventlet
eventlet.Timeout(0.5)
try:
eventlet.listen(("127.0.0.1", 0)).accept()
except eventlet.Timeout:
print("exited correctly")
""")
fd.close()
python_path = os.pathsep.join(sys.path + [self.tempdir])
new_env = os.environ.copy()
new_env['PYTHONPATH'] = python_path
p = subprocess.Popen([sys.executable,
os.path.join(self.tempdir, filename)],
stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env=new_env)
eventlet.sleep(0.4) # wait for process to hit accept
os.kill(p.pid, signal.SIGSTOP) # suspend and resume to generate EINTR
os.kill(p.pid, signal.SIGCONT)
output, _ = p.communicate()
lines = output.decode('utf-8', 'replace').splitlines()
assert "exited correctly" in lines[-1], output
shutil.rmtree(self.tempdir)
def pause(self):
"""Pause the process by sending a SIGSTOP to the child"""
try:
self.command_process.stdin.write("STOP\n")
self.command_process.stdin.flush()
except IOError as exc:
if exc.errno == 32: # Broken pipe, guard exited
return
raise
item = self.resp_queue.get()
if item[1] != "STOP" and item[1] is not None:
raise SandboxError("Bad response from jailguard after pause, %s"
% (item,))
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
def handler_sigstop(signum, stack):
resetterm()
os.kill(os.getpid(), signal.SIGSTOP)
def pause(self):
"""Pause the process by sending a SIGSTOP to the child"""
try:
self.command_process.stdin.write("STOP\n")
self.command_process.stdin.flush()
except IOError as exc:
if exc.errno == 32: # Broken pipe, guard exited
return
raise
item = self.resp_queue.get()
if item[1] != "STOP" and item[1] is not None:
raise SandboxError("Bad response from jailguard after pause, %s"
% (item,))