Show More
@@ -134,37 +134,43 b' def _posixworker(ui, func, staticargs, a' | |||
|
134 | 134 | killworkers() |
|
135 | 135 | oldchldhandler = signal.signal(signal.SIGCHLD, sigchldhandler) |
|
136 | 136 | ui.flush() |
|
137 | parentpid = os.getpid() | |
|
137 | 138 | for pargs in partition(args, workers): |
|
138 | pid = os.fork() | |
|
139 | if pid == 0: | |
|
140 | signal.signal(signal.SIGINT, oldhandler) | |
|
141 | signal.signal(signal.SIGCHLD, oldchldhandler) | |
|
142 | ||
|
143 | def workerfunc(): | |
|
144 | os.close(rfd) | |
|
145 | for i, item in func(*(staticargs + (pargs,))): | |
|
146 | os.write(wfd, '%d %s\n' % (i, item)) | |
|
147 | return 0 | |
|
139 | # make sure we use os._exit in all worker code paths. otherwise the | |
|
140 | # worker may do some clean-ups which could cause surprises like | |
|
141 | # deadlock. see sshpeer.cleanup for example. | |
|
142 | # override error handling *before* fork. this is necessary because | |
|
143 | # exception (signal) may arrive after fork, before "pid =" assignment | |
|
144 | # completes, and other exception handler (dispatch.py) can lead to | |
|
145 | # unexpected code path without os._exit. | |
|
146 | ret = -1 | |
|
147 | try: | |
|
148 | pid = os.fork() | |
|
149 | if pid == 0: | |
|
150 | signal.signal(signal.SIGINT, oldhandler) | |
|
151 | signal.signal(signal.SIGCHLD, oldchldhandler) | |
|
148 | 152 | |
|
149 | # make sure we use os._exit in all code paths. otherwise the worker | |
|
150 | # may do some clean-ups which could cause surprises like deadlock. | |
|
151 | # see sshpeer.cleanup for example. | |
|
152 | ret = 0 | |
|
153 |
|
|
|
153 | def workerfunc(): | |
|
154 | os.close(rfd) | |
|
155 | for i, item in func(*(staticargs + (pargs,))): | |
|
156 | os.write(wfd, '%d %s\n' % (i, item)) | |
|
157 | return 0 | |
|
158 | ||
|
159 | ret = scmutil.callcatch(ui, workerfunc) | |
|
160 | except: # parent re-raises, child never returns | |
|
161 | if os.getpid() == parentpid: | |
|
162 | raise | |
|
163 | exctype = sys.exc_info()[0] | |
|
164 | force = not issubclass(exctype, KeyboardInterrupt) | |
|
165 | ui.traceback(force=force) | |
|
166 | finally: | |
|
167 | if os.getpid() != parentpid: | |
|
154 | 168 | try: |
|
155 | ret = scmutil.callcatch(ui, workerfunc) | |
|
156 | finally: | |
|
157 | 169 | ui.flush() |
|
158 | except KeyboardInterrupt: | |
|
159 |
|
|
|
160 | except: # never return, therefore no re-raises | |
|
161 | try: | |
|
162 | ui.traceback(force=True) | |
|
163 | ui.flush() | |
|
170 | except: # never returns, no re-raises | |
|
171 | pass | |
|
164 | 172 | finally: |
|
165 | os._exit(255) | |
|
166 | else: | |
|
167 | os._exit(ret & 255) | |
|
173 | os._exit(ret & 255) | |
|
168 | 174 | pids.add(pid) |
|
169 | 175 | os.close(wfd) |
|
170 | 176 | fp = os.fdopen(rfd, pycompat.sysstr('rb'), 0) |
@@ -91,4 +91,36 b' Traceback must be printed for unknown ex' | |||
|
91 | 91 | > test 100000.0 exc 2>&1 | grep '^Traceback' |
|
92 | 92 | Traceback (most recent call last): |
|
93 | 93 | |
|
94 | Workers should not do cleanups in all cases | |
|
95 | ||
|
96 | $ cat > $TESTTMP/detectcleanup.py <<EOF | |
|
97 | > from __future__ import absolute_import | |
|
98 | > import atexit | |
|
99 | > import os | |
|
100 | > import time | |
|
101 | > oldfork = os.fork | |
|
102 | > count = 0 | |
|
103 | > parentpid = os.getpid() | |
|
104 | > def delayedfork(): | |
|
105 | > global count | |
|
106 | > count += 1 | |
|
107 | > pid = oldfork() | |
|
108 | > # make it easier to test SIGTERM hitting other workers when they have | |
|
109 | > # not set up error handling yet. | |
|
110 | > if count > 1 and pid == 0: | |
|
111 | > time.sleep(0.1) | |
|
112 | > return pid | |
|
113 | > os.fork = delayedfork | |
|
114 | > def cleanup(): | |
|
115 | > if os.getpid() != parentpid: | |
|
116 | > os.write(1, 'should never happen\n') | |
|
117 | > atexit.register(cleanup) | |
|
118 | > EOF | |
|
119 | ||
|
120 | $ hg --config "extensions.t=$abspath" --config worker.numcpus=8 --config \ | |
|
121 | > "extensions.d=$TESTTMP/detectcleanup.py" test 100000 abort | |
|
122 | start | |
|
123 | abort: known exception | |
|
124 | [255] | |
|
125 | ||
|
94 | 126 | #endif |
General Comments 0
You need to be logged in to leave comments.
Login now