Stefan Scherfke avatar Stefan Scherfke committed 5682006

Added a minimal example for sigterm and found a solution on how to send sigbreak into processes.

Comments (0)

Files changed (4)

 
 
 def parent():
+    print('parent started')
     proc = subprocess.Popen(['python', 'ctrl_c.py', 'child'])
     try:
         time.sleep(60)
 
 
 def child():
+    print('child started')
     try:
         time.sleep(60)
     except KeyboardInterrupt:
 
 - Linux
 - OS X
-- Windows?
 
 """
 import signal
 - Windows?
 
 """
+import os
 import signal
 import subprocess
 import sys
 import time
 
 
+WIN = (sys.platform == 'win32')
+kwargs = {}
+if WIN:
+    kwargs['creationflags'] = subprocess.CREATE_NEW_PROCESS_GROUP
+
+
 def parent():
-    proc = subprocess.Popen(['python', 'sigterm.py', 'child'])
+    proc = subprocess.Popen(['python', 'sigterm.py', 'child'], **kwargs)
 
-    def handler(signum, frame):
-        # Uncomment these lines to see that "sig" is not forwarded
-        # automatically.
+    def handler(signum, frame=None):
         print('parent received SIGTERM')
-        proc.send_signal(signal.SIGTERM)
-        # proc.terminate()
+        if WIN:
+            # import ctypes
+            # ctypes.windll.kernel32.GenerateConsoleCtrlEvent(signal.CTRL_BREAK_EVENT, proc.pid)
+            os.kill(proc.pid, signal.CTRL_BREAK_EVENT)
+        else:
+            proc.terminate()
 
         print('parent waiting for child')
         proc.wait()
         print('parent terminating')
         sys.exit(0)
 
-    signal.signal(signal.SIGTERM, handler)
+    if WIN:
+        import ctypes
+        handler = ctypes.WINFUNCTYPE(ctypes.c_int, ctypes.c_uint)(handler)
+        ctypes.windll.kernel32.SetConsoleCtrlHandler(handler, True)
+        # signal.signal(signal.SIGBREAK, handler)
+    else:
+        signal.signal(signal.SIGTERM, handler)
     time.sleep(60)
 
 
 def child():
-    def handler(signum, frame):
+    def handler(signum, frame=None):
         print('child terminating')
         sys.exit(0)
 
-    signal.signal(signal.SIGTERM, handler)
+    if WIN:
+        import ctypes
+        handler = ctypes.WINFUNCTYPE(ctypes.c_int, ctypes.c_uint)(handler)
+        ctypes.windll.kernel32.SetConsoleCtrlHandler(handler, True)
+        # signal.signal(signal.SIGBREAK, handler)
+    else:
+        signal.signal(signal.SIGTERM, handler)
     time.sleep(60)
 
 
 if __name__ == '__main__':
     if len(sys.argv) == 1:
-        proc = subprocess.Popen(['python', 'sigterm.py', 'parent'])
+        proc = subprocess.Popen(['python', 'sigterm.py', 'parent'], **kwargs)
         time.sleep(1)
         print('Sending SIGTERM to parent')
-        proc.send_signal(signal.SIGTERM)
-        # proc.terminate()
+        if WIN:
+            # import ctypes
+            # ctypes.windll.kernel32.GenerateConsoleCtrlEvent(signal.CTRL_BREAK_EVENT, proc.pid)
+            os.kill(proc.pid, signal.CTRL_BREAK_EVENT)
+        else:
+            proc.terminate()
         print('Waiting for parent')
         proc.wait()
     elif sys.argv[1] == 'parent':
+import os
+import signal
+import subprocess
+import sys
+import time
+
+
+WIN = (sys.platform == 'win32')
+kwargs = {}
+if WIN:
+    kwargs['creationflags'] = subprocess.CREATE_NEW_PROCESS_GROUP
+
+
+def parent():
+    proc = subprocess.Popen(['python', 'sigterm_min.py', 'child'], **kwargs)
+    time.sleep(1)
+
+    if WIN:
+        # This works on Python 2.7 and 3.3:
+        os.kill(proc.pid, signal.CTRL_BREAK_EVENT)
+
+        # Alternative (ugly) way:
+        # import ctypes
+        # ctypes.windll.kernel32.GenerateConsoleCtrlEvent(signal.CTRL_BREAK_EVENT, proc.pid)
+    else:
+        proc.terminate()
+
+    print('parent waiting for child')
+    proc.wait()
+    print('parent terminating')
+
+
+def child():
+    def handler(signum, frame=None):
+        print('child terminating')
+        sys.exit(0)
+
+    if WIN:
+        # This only works on Python 2.7, but not on 3.3:
+        signal.signal(signal.SIGBREAK, handler)
+
+        # (Ugly) alternative that works on both Python 2.7 and 3.3,
+        # but raises a KeyError in threading.py:
+        # import ctypes
+        # handler = ctypes.WINFUNCTYPE(ctypes.c_int, ctypes.c_uint)(handler)
+        # ctypes.windll.kernel32.SetConsoleCtrlHandler(handler, True)
+    else:
+        signal.signal(signal.SIGTERM, handler)
+
+    time.sleep(10)
+
+
+if __name__ == '__main__':
+    if len(sys.argv) == 1:
+        parent()
+    elif sys.argv[1] == 'child':
+        child()
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.