def main(): # build "all signals" list allsigv = [] for attr in dir(syscall): if attr.startswith("SIG") and "_" not in attr: sig = getattr(syscall, attr) if sig not in allsigv: # avoid e.g. SIGCHLD/SIGCLD dups allsigv.append(sig) allsigv.sort(key=lambda sig: sig.signo) allsigv.remove(syscall.SIGKILL) # SIGKILL/SIGSTOP cannot be caught allsigv.remove(syscall.SIGSTOP) allsigv.remove(syscall.SIGBUS) # AddressSanitizer crashes on SIGBUS/SIGFPE/SIGSEGV allsigv.remove(syscall.SIGFPE) allsigv.remove(syscall.SIGSEGV) # Notify() -> kill * -> should be notified ch = chan(10, dtype=gos.Signal) signal.Notify(ch) # all signals for sig in allsigv: emit("-> %d %s" % (sig.signo, sig)) killme(sig) xsig = ch.recv() emit("<- %d %s" % (xsig.signo, xsig)) if xsig != sig: raise AssertionError("got %s, expected %s" % (xsig, sig)) emit("ok (notify)") # Ignore() -> kill * -> should not be notified emit() signal.Ignore() # all signals assert len(ch) == 0 for sig in allsigv: emit("-> %d %s" % (sig.signo, sig)) killme(sig) assert len(ch) == 0 time.sleep(0.3) assert len(ch) == 0 emit("ok (ignore)") # Reset() -> kill * should be handled by OS by default emit() signal.Reset() # all signals emit("terminating ...") killme(syscall.SIGTERM) raise AssertionError("not terminated")
def _(): signal.Reset()
def test_signal(): # Notify/Stop with wrong chan dtype -> panic _ = panics("pychan: channel type mismatch") with _: signal.Notify(chan(2), syscall.SIGUSR1) with _: signal.Stop (chan(2)) with _: signal.Notify(chan(2, dtype='C.int'), syscall.SIGUSR1) with _: signal.Stop (chan(2, dtype='C.int')) # Notify/Ignore/Reset with wrong signal type _ = raises(TypeError) with _: signal.Notify(chan(dtype=gos.Signal), None) with _: signal.Ignore(None) with _: signal.Reset(None) # subscribe ch1(USR1), ch12(USR1,USR2) and ch2(USR2) ch1 = chan(2, dtype=gos.Signal) ch12 = chan(2, dtype=gos.Signal) ch2 = chan(2, dtype=gos.Signal) signal.Notify(ch1, syscall.SIGUSR1) signal.Notify(ch12, syscall.SIGUSR1, syscall.SIGUSR2) signal.Notify(ch2, syscall.SIGUSR2) def _(): signal.Reset() defer(_) for i in range(N): # raise SIGUSR1 -> should be delivered to ch1 and ch12 assert len(ch1) == 0 assert len(ch12) == 0 assert len(ch2) == 0 killme(syscall.SIGUSR1) waitfor(lambda: len(ch1) == 1 and len(ch12) == 1) sig1 = ch1.recv() sig12 = ch12.recv() assert sig1 == syscall.SIGUSR1 assert sig12 == syscall.SIGUSR1 # raise SIGUSR2 -> should be delivered to ch12 and ch2 assert len(ch1) == 0 assert len(ch12) == 0 assert len(ch2) == 0 killme(syscall.SIGUSR2) waitfor(lambda: len(ch12) == 1 and len(ch2) == 1) sig12 = ch12.recv() sig2 = ch2.recv() assert sig12 == syscall.SIGUSR2 assert sig2 == syscall.SIGUSR2 # if SIGUSR2 will be eventually delivered to ch1 - it will break # in SIGUSR1 check on next iteration. # Stop(ch2) -> signals should not be delivered to ch2 anymore signal.Stop(ch2) for i in range(N): # USR1 -> ch1, ch12 assert len(ch1) == 0 assert len(ch12) == 0 assert len(ch2) == 0 killme(syscall.SIGUSR1) waitfor(lambda: len(ch1) == 1 and len(ch12) == 1) sig1 = ch1.recv() sig12 = ch12.recv() assert sig1 == syscall.SIGUSR1 assert sig12 == syscall.SIGUSR1 # USR2 -> ch12, !ch2 assert len(ch1) == 0 assert len(ch12) == 0 assert len(ch2) == 0 killme(syscall.SIGUSR2) waitfor(lambda: len(ch12) == 1) sig12 = ch12.recv() assert sig12 == syscall.SIGUSR2 # if SIGUSR2 will be eventually delivered to ch2 - it will break on # next iteration. # Ignore(USR1) -> ch1 should not be delivered to anymore, ch12 should be delivered only USR2 signal.Ignore(syscall.SIGUSR1) for i in range(N): # USR1 -> ø assert len(ch1) == 0 assert len(ch12) == 0 assert len(ch2) == 0 killme(syscall.SIGUSR1) time.sleep(1E-6) # USR2 -> ch12 assert len(ch1) == 0 assert len(ch12) == 0 assert len(ch2) == 0 killme(syscall.SIGUSR2) waitfor(lambda: len(ch12) == 1) sig12 = ch12.recv() assert sig12 == syscall.SIGUSR2 # if SIGUSR1 or SIGUSR2 will be eventually delivered to ch1 or ch2 - it # will break on next iteration. # Notify after Ignore signal.Notify(ch1, syscall.SIGUSR1) for i in range(N): # USR1 -> ch1 assert len(ch1) == 0 assert len(ch12) == 0 assert len(ch2) == 0 killme(syscall.SIGUSR1) waitfor(lambda: len(ch1) == 1) sig1 = ch1.recv() assert sig1 == syscall.SIGUSR1 # USR2 -> ch12 assert len(ch1) == 0 assert len(ch12) == 0 assert len(ch2) == 0 killme(syscall.SIGUSR2) waitfor(lambda: len(ch12) == 1) sig12 = ch12.recv() assert sig12 == syscall.SIGUSR2
def _(): signal.Reset(syscall.SIGINT)
def test_stdlib_interop_KeyboardInterrupt(): # KeyboardInterrupt is raised by default with raises(KeyboardInterrupt): killme(syscall.SIGINT) time.sleep(1) ch1 = chan(2, dtype=gos.Signal) ch2 = chan(2, dtype=gos.Signal) def _(): signal.Reset(syscall.SIGINT) defer(_) # Notify disables raising KeyboardInterrupt by default on SIGINT signal.Notify(ch1, syscall.SIGINT) try: killme(syscall.SIGINT) waitfor(lambda: len(ch1) == 1) obj1 = ch1.recv() assert obj1 == syscall.SIGINT time.sleep(0.1) # just in case except KeyboardInterrupt: raise AssertionError("KeyboardInterrupt raised after signal.Notify +ch1") signal.Notify(ch2, syscall.SIGINT) try: killme(syscall.SIGINT) waitfor(lambda: len(ch1) == 1 and len(ch2) == 1) obj1 = ch1.recv() obj2 = ch2.recv() assert obj1 == syscall.SIGINT assert obj2 == syscall.SIGINT time.sleep(0.1) # just in case except KeyboardInterrupt: raise AssertionError("KeyboardInterrupt raised after signal.Notify +ch1 +ch2") # last Stop should reenable raising KeyboardInterrupt by default on SIGINT signal.Stop(ch1) try: killme(syscall.SIGINT) waitfor(lambda: len(ch2) == 1) obj2 = ch2.recv() assert obj2 == syscall.SIGINT time.sleep(0.1) # just in case assert len(ch1) == 0 except KeyboardInterrupt: raise AssertionError("KeyboardInterrupt raised after signal.Notify +ch1 +ch2 -ch1") signal.Stop(ch2) with raises(KeyboardInterrupt): killme(syscall.SIGINT) time.sleep(1) time.sleep(0.1) # just in case assert len(ch1) == 0 assert len(ch2) == 0 # Ignore disables raising KeyboardInterrupt by default on SIGINT signal.Ignore(syscall.SIGINT) try: killme(syscall.SIGINT) time.sleep(0.1) assert len(ch1) == 0 assert len(ch2) == 0 except KeyboardInterrupt: raise AssertionError("KeyboardInterrupt raised after signal.Ignore") # Reset restores original behaviour signal.Reset(syscall.SIGINT) with raises(KeyboardInterrupt): killme(syscall.SIGINT) time.sleep(1) time.sleep(0.1) # just in case assert len(ch1) == 0 assert len(ch2) == 0
def test_stdlib_interop(): import signal as pysig ch1 = chan(2, dtype=object) # NOTE not gos.Signal nor 'C.os::Signal' def _(signo, frame): ch1.send("USR1") pysig.signal(pysig.SIGUSR1, _) def _(): pysig.signal(pysig.SIGUSR1, pysig.SIG_IGN) defer(_) # verify that plain pysig delivery works for i in range(N): assert len(ch1) == 0 killme(syscall.SIGUSR1) waitfor(lambda: len(ch1) == 1) obj1 = ch1.recv() assert obj1 == "USR1" # verify that combined pysig + golang.os.signal delivery works ch2 = chan(2, dtype=gos.Signal) signal.Notify(ch2, syscall.SIGUSR1) def _(): signal.Stop(ch2) defer(_) for i in range(N): assert len(ch1) == 0 assert len(ch2) == 0 killme(syscall.SIGUSR1) waitfor(lambda: len(ch1) == 1 and len(ch2) == 1) obj1 = ch1.recv() sig2 = ch2.recv() assert obj1 == "USR1" assert sig2 == syscall.SIGUSR1 # Ignore stops delivery to both pysig and golang.os.signal signal.Ignore(syscall.SIGUSR1) for i in range(N): assert len(ch1) == 0 assert len(ch2) == 0 killme(syscall.SIGUSR1) time.sleep(1E-6) time.sleep(0.1) # just in case assert len(ch1) == 0 assert len(ch2) == 0 # after Reset pysig delivery is restored even after Ignore signal.Reset(syscall.SIGUSR1) for i in range(N): assert len(ch1) == 0 assert len(ch2) == 0 killme(syscall.SIGUSR1) waitfor(lambda: len(ch1) == 1) assert len(ch2) == 0 obj1 = ch1.recv() assert obj1 == "USR1" # Reset stops delivery to golang.os.signal and restores pysig delivery signal.Notify(ch2, syscall.SIGUSR1) signal.Reset(syscall.SIGUSR1) for i in range(N): assert len(ch1) == 0 assert len(ch2) == 0 killme(syscall.SIGUSR1) waitfor(lambda: len(ch1) == 1) assert len(ch2) == 0 obj1 = ch1.recv() assert obj1 == "USR1"