Skip to content

Commit

Permalink
[signal-handling] Fix exit code of 'wait' on trapped signal.
Browse files Browse the repository at this point in the history
This completes a fix for 'wait builtin should be interruptible'.  That
wasn't entirely correct.

Also add tests case for SIGINT.

- SIGINT when trapped correctly gives status=130
- SIGINT when not trapped doesn't give the right status.  This has to do
  with KeyboardInterrupt.  So yes we should always trap it!  This is
  #896.

Also suppress color in test/interactive then output isn't a TTY.
  • Loading branch information
Andy C committed Jan 27, 2022
1 parent d22664a commit 985de3c
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 8 deletions.
11 changes: 8 additions & 3 deletions osh/builtin_process.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,20 +155,25 @@ def _Run(self, cmd_val):

if len(job_ids) == 0:
#log('*** wait')
status = 0
i = 0
while True:
# BUG: If there is a STOPPED process, this will hang forever, because
# we don't get ECHILD.
# Not sure it matters since you can now Ctrl-C it.

result = self.waiter.WaitForOne(False)
if result != 0:
break # nothing to wait for, or interrupted
if result == -1: # nothing to wait for, or interrupted. status is 0
break
elif result > 128: # signal
status = result
break

i += 1
if self.job_state.NoneAreRunning():
break

return 0 if result == -1 else result
return status

# Get list of jobs. Then we need to check if they are ALL stopped.
# Returns the exit code of the last one on the COMMAND LINE, not the exit
Expand Down
59 changes: 54 additions & 5 deletions test/interactive.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,10 +119,50 @@ def decorator(func):
# 3. trap 'echo X' SIGINT ?


@register()
def trapped_1(sh):
'trapped SIG during wait builtin'

sh.sendline("trap 'echo HUP' HUP")
sh.sendline('sleep 1 &')
sh.sendline('wait')

time.sleep(0.1)

# simulate window size change
sh.kill(signal.SIGHUP)

sh.expect(r'.*\$') # expect prompt

sh.sendline('echo status=$?')
sh.expect('status=129')


@register()
def trapped_sigint(sh):
'trapped SIGINT during wait builtin'

# This is different than Ctrl-C during wait builtin, because it's trapped!

sh.sendline("trap 'echo INT' INT")
sh.sendline('sleep 1 &')
sh.sendline('wait')

time.sleep(0.1)

# simulate window size change
sh.kill(signal.SIGINT)

sh.expect(r'.*\$') # expect prompt

sh.sendline('echo status=$?')
sh.expect('status=130')


# TODO: Make this pass in OSH
@register()
def t0(sh):
'wait builtin then SIGWINCH (issue 1067)'
def sigwinch_1(sh):
'SIGWINCH during wait builtin (issue 1067)'

sh.sendline('sleep 1 &')
sh.sendline('wait')
Expand Down Expand Up @@ -379,7 +419,16 @@ def RunCases(cases, case_predicate, shell_pairs, results):


def PrintResults(shell_pairs, results):
f = sys.stderr
f = sys.stdout

if f.isatty():
fail_color = ansi.BOLD + ansi.RED
ok_color = ansi.BOLD + ansi.GREEN
reset = ansi.RESET
else:
fail_color = ''
ok_color = ''
reset = ''

f.write('\n')

Expand All @@ -401,9 +450,9 @@ def PrintResults(shell_pairs, results):
f.write('SKIP\t')
elif cell == Result.FAIL:
status = 1
f.write('%sFAIL%s\t' % (ansi.BOLD + ansi.RED, ansi.RESET))
f.write('%sFAIL%s\t' % (fail_color, reset))
elif cell == Result.OK:
f.write('%sok%s\t' % (ansi.BOLD + ansi.GREEN, ansi.RESET))
f.write('%sok%s\t' % (ok_color, reset))
else:
raise AssertionError(cell)

Expand Down

0 comments on commit 985de3c

Please sign in to comment.