##// END OF EJS Templates
Remove print statements in ZMQ parent pollers....
Evan Patterson -
Show More
@@ -1,125 +1,119 b''
1 # Standard library imports.
1 # Standard library imports.
2 import ctypes
2 import ctypes
3 import os
3 import os
4 import time
4 import time
5 from thread import interrupt_main
5 from thread import interrupt_main
6 from threading import Thread
6 from threading import Thread
7
7
8 # Local imports.
9 from IPython.utils.io import raw_print
10
11
8
12 class ParentPollerUnix(Thread):
9 class ParentPollerUnix(Thread):
13 """ A Unix-specific daemon thread that terminates the program immediately
10 """ A Unix-specific daemon thread that terminates the program immediately
14 when the parent process no longer exists.
11 when the parent process no longer exists.
15 """
12 """
16
13
17 def __init__(self):
14 def __init__(self):
18 super(ParentPollerUnix, self).__init__()
15 super(ParentPollerUnix, self).__init__()
19 self.daemon = True
16 self.daemon = True
20
17
21 def run(self):
18 def run(self):
22 # We cannot use os.waitpid because it works only for child processes.
19 # We cannot use os.waitpid because it works only for child processes.
23 from errno import EINTR
20 from errno import EINTR
24 while True:
21 while True:
25 try:
22 try:
26 if os.getppid() == 1:
23 if os.getppid() == 1:
27 raw_print('Killed by parent poller!')
28 os._exit(1)
24 os._exit(1)
29 time.sleep(1.0)
25 time.sleep(1.0)
30 except OSError, e:
26 except OSError, e:
31 if e.errno == EINTR:
27 if e.errno == EINTR:
32 continue
28 continue
33 raise
29 raise
34
30
35
31
36 class ParentPollerWindows(Thread):
32 class ParentPollerWindows(Thread):
37 """ A Windows-specific daemon thread that listens for a special event that
33 """ A Windows-specific daemon thread that listens for a special event that
38 signals an interrupt and, optionally, terminates the program immediately
34 signals an interrupt and, optionally, terminates the program immediately
39 when the parent process no longer exists.
35 when the parent process no longer exists.
40 """
36 """
41
37
42 def __init__(self, interrupt_handle=None, parent_handle=None):
38 def __init__(self, interrupt_handle=None, parent_handle=None):
43 """ Create the poller. At least one of the optional parameters must be
39 """ Create the poller. At least one of the optional parameters must be
44 provided.
40 provided.
45
41
46 Parameters:
42 Parameters:
47 -----------
43 -----------
48 interrupt_handle : HANDLE (int), optional
44 interrupt_handle : HANDLE (int), optional
49 If provided, the program will generate a Ctrl+C event when this
45 If provided, the program will generate a Ctrl+C event when this
50 handle is signaled.
46 handle is signaled.
51
47
52 parent_handle : HANDLE (int), optional
48 parent_handle : HANDLE (int), optional
53 If provided, the program will terminate immediately when this
49 If provided, the program will terminate immediately when this
54 handle is signaled.
50 handle is signaled.
55 """
51 """
56 assert(interrupt_handle or parent_handle)
52 assert(interrupt_handle or parent_handle)
57 super(ParentPollerWindows, self).__init__()
53 super(ParentPollerWindows, self).__init__()
58 self.daemon = True
54 self.daemon = True
59 self.interrupt_handle = interrupt_handle
55 self.interrupt_handle = interrupt_handle
60 self.parent_handle = parent_handle
56 self.parent_handle = parent_handle
61
57
62 @staticmethod
58 @staticmethod
63 def create_interrupt_event():
59 def create_interrupt_event():
64 """ Create an interrupt event handle.
60 """ Create an interrupt event handle.
65
61
66 The parent process should use this static method for creating the
62 The parent process should use this static method for creating the
67 interrupt event that is passed to the child process. It should store
63 interrupt event that is passed to the child process. It should store
68 this handle and use it with ``send_interrupt`` to interrupt the child
64 this handle and use it with ``send_interrupt`` to interrupt the child
69 process.
65 process.
70 """
66 """
71 # Create a security attributes struct that permits inheritance of the
67 # Create a security attributes struct that permits inheritance of the
72 # handle by new processes.
68 # handle by new processes.
73 # FIXME: We can clean up this mess by requiring pywin32 for IPython.
69 # FIXME: We can clean up this mess by requiring pywin32 for IPython.
74 class SECURITY_ATTRIBUTES(ctypes.Structure):
70 class SECURITY_ATTRIBUTES(ctypes.Structure):
75 _fields_ = [ ("nLength", ctypes.c_int),
71 _fields_ = [ ("nLength", ctypes.c_int),
76 ("lpSecurityDescriptor", ctypes.c_void_p),
72 ("lpSecurityDescriptor", ctypes.c_void_p),
77 ("bInheritHandle", ctypes.c_int) ]
73 ("bInheritHandle", ctypes.c_int) ]
78 sa = SECURITY_ATTRIBUTES()
74 sa = SECURITY_ATTRIBUTES()
79 sa_p = ctypes.pointer(sa)
75 sa_p = ctypes.pointer(sa)
80 sa.nLength = ctypes.sizeof(SECURITY_ATTRIBUTES)
76 sa.nLength = ctypes.sizeof(SECURITY_ATTRIBUTES)
81 sa.lpSecurityDescriptor = 0
77 sa.lpSecurityDescriptor = 0
82 sa.bInheritHandle = 1
78 sa.bInheritHandle = 1
83
79
84 return ctypes.windll.kernel32.CreateEventA(
80 return ctypes.windll.kernel32.CreateEventA(
85 sa_p, # lpEventAttributes
81 sa_p, # lpEventAttributes
86 False, # bManualReset
82 False, # bManualReset
87 False, # bInitialState
83 False, # bInitialState
88 '') # lpName
84 '') # lpName
89
85
90 @staticmethod
86 @staticmethod
91 def send_interrupt(interrupt_handle):
87 def send_interrupt(interrupt_handle):
92 """ Sends an interrupt event using the specified handle.
88 """ Sends an interrupt event using the specified handle.
93 """
89 """
94 ctypes.windll.kernel32.SetEvent(interrupt_handle)
90 ctypes.windll.kernel32.SetEvent(interrupt_handle)
95
91
96 def run(self):
92 def run(self):
97 """ Run the poll loop. This method never returns.
93 """ Run the poll loop. This method never returns.
98 """
94 """
99 from _subprocess import WAIT_OBJECT_0, INFINITE
95 from _subprocess import WAIT_OBJECT_0, INFINITE
100
96
101 # Build the list of handle to listen on.
97 # Build the list of handle to listen on.
102 handles = []
98 handles = []
103 if self.interrupt_handle:
99 if self.interrupt_handle:
104 handles.append(self.interrupt_handle)
100 handles.append(self.interrupt_handle)
105 if self.parent_handle:
101 if self.parent_handle:
106 handles.append(self.parent_handle)
102 handles.append(self.parent_handle)
107
103
108 # Listen forever.
104 # Listen forever.
109 while True:
105 while True:
110 result = ctypes.windll.kernel32.WaitForMultipleObjects(
106 result = ctypes.windll.kernel32.WaitForMultipleObjects(
111 len(handles), # nCount
107 len(handles), # nCount
112 (ctypes.c_int * len(handles))(*handles), # lpHandles
108 (ctypes.c_int * len(handles))(*handles), # lpHandles
113 False, # bWaitAll
109 False, # bWaitAll
114 INFINITE) # dwMilliseconds
110 INFINITE) # dwMilliseconds
115
111
116 if WAIT_OBJECT_0 <= result < len(handles):
112 if WAIT_OBJECT_0 <= result < len(handles):
117 handle = handles[result - WAIT_OBJECT_0]
113 handle = handles[result - WAIT_OBJECT_0]
118
114
119 if handle == self.interrupt_handle:
115 if handle == self.interrupt_handle:
120 raw_print('Interrupted by parent poller!')
121 interrupt_main()
116 interrupt_main()
122
117
123 elif handle == self.parent_handle:
118 elif handle == self.parent_handle:
124 raw_print('Killed by parent poller!')
125 os._exit(1)
119 os._exit(1)
General Comments 0
You need to be logged in to leave comments. Login now