Skip to content

Commit

Permalink
[test/stateful] Repro for SIGTSTP issue
Browse files Browse the repository at this point in the history
Child processes appear to be ignoring it... why?  It seems like it could
be a Python interpreter thing, but I see no evidence of that.
  • Loading branch information
Andy C committed Feb 19, 2022
1 parent 250fce8 commit d1a5037
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 28 deletions.
49 changes: 32 additions & 17 deletions demo/cpython/fork_signal_state.py
Expand Up @@ -39,28 +39,43 @@ def main(argv):
SignalState(parent_pid)
log('===')

pid = os.fork()
if pid == 0:
child_pid = os.getpid()
line = raw_input()

log('---')
SignalState(child_pid)
signal.signal(signal.SIGTSTP, signal.SIG_DFL)
SignalState(child_pid)
log('---')
if line.startswith('sleep'):
pid = os.fork()
if pid == 0:
child_pid = os.getpid()

log('sleep 1 in child %d', child_pid)
time.sleep(1)
log('---')
SignalState(child_pid)
signal.signal(signal.SIGTSTP, signal.SIG_DFL)
SignalState(child_pid)
log('---')

elif pid < 0:
raise AssertionError()
log('sleep 1 in child %d', child_pid)
os.execve('/bin/sleep', ['sleep', '1'], {})

else:
log('parent spawned %d', pid)
elif pid < 0:
raise AssertionError()

else:
log('parent spawned %d', pid)

log('waiting')
pid, status = os.waitpid(-1, os.WUNTRACED)
log('wait => pid %d exited with status %d', pid, status)

if os.WIFEXITED(status):
log('EXITED')

log('waiting')
result = os.waitpid(-1, 0)
log('wait => %s', result)
if os.WIFSIGNALED(status):
log('SIGNALED')

elif os.WIFSTOPPED(status):
log('STOPPED')

else:
log('BAD COMMAND')


if __name__ == '__main__':
Expand Down
46 changes: 38 additions & 8 deletions spec/stateful/harness.py
Expand Up @@ -33,20 +33,15 @@ def get_pid_by_name(name):
return int(output.split()[-1])


def send_signal(name, sig_num):
"""Kill the most recent process matching `name`."""
os.kill(get_pid_by_name(name), sig_num)


def stop_process__hack(name):
"""Send sigstop to the most recent process matching `name`
def stop_process__hack(name, sig_num=signal.SIGSTOP):
"""Send SIGSTOP to the most recent process matching `name`
Hack in place of sh.sendcontrol('z'), which sends SIGTSTP. Why doesn't OSH
respond to this, or why don't the child processes respond?
TODO: Fix OSH and get rid of this hack.
"""
send_signal(name, signal.SIGSTOP)
os.kill(get_pid_by_name(name), sig_num)


# Mutated by each test file.
Expand Down Expand Up @@ -235,11 +230,46 @@ def PrintResults(shell_pairs, result_table, flaky, num_retries, f):
return num_failures


def TestStop(exe):
p = pexpect.spawn(exe, encoding='utf-8', timeout=2.0)

# Show output
p.logfile = sys.stdout
#p.setecho(True)

p.sendline('sleep')
p.expect('in child')

import time
time.sleep(0.1)

# Stop it

if 0: # does NOT work -- why?
p.sendcontrol('z')
if 0: # does NOT work
stop_process__hack('sleep', sig_num=signal.SIGTSTP)
if 1:
# WORKS
stop_process__hack('sleep', sig_num=signal.SIGSTOP)

# These will kill the parent, not the sleep child
#p.kill(signal.SIGTSTP)
#p.kill(signal.SIGSTOP)

p.expect('wait =>')
p.close()


def main(argv):
# NOTE: Some options are ignored
o = spec_lib.Options()
opts, argv = o.parse_args(argv)

if argv and argv[1] == 'test-stop': # Hack for testing
TestStop(argv[2])
return

# List test cases and return
if opts.do_list:
for i, (desc, _, _) in enumerate(CASES):
Expand Down
18 changes: 15 additions & 3 deletions spec/stateful/job_control.py
Expand Up @@ -54,11 +54,23 @@ def bug_1004(sh):

time.sleep(0.1)

if 0:
debug = False
#debug = True

if debug:
import os
os.system('ls -l /proc/%s/fd' % os.getpid())
#os.system('ls -l /proc/%s/fd' % os.getpid())

if 0:
# From test/group-session.sh
log('harness PID = %d', os.getpid())
import subprocess
#os.system('ps -o pid,ppid,pgid,sid,tpgid,comm')

# the child shell is NOT LISTED here because it's associated WITH A
# DIFFERENT TERMINAL.
subprocess.call(['ps', '-o', 'pid,ppid,pgid,sid,tpgid,comm'])

if debug:
ctrl_z(sh)
else:
stop_process__hack('cat')
Expand Down
8 changes: 8 additions & 0 deletions test/stateful.sh
Expand Up @@ -190,4 +190,12 @@ soil-run() {
all
}

#
# Debugging
#

test-stop() {
python3 spec/stateful/harness.py test-stop demo/cpython/fork_signal_state.py
}

"$@"

0 comments on commit d1a5037

Please sign in to comment.