##// END OF EJS Templates
worker: handle worker failures more aggressively...
Bryan O'Sullivan -
r18709:9955fc5e default
parent child Browse files
Show More
@@ -6,7 +6,7 b''
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from i18n import _
8 from i18n import _
9 import os, signal, sys, util
9 import os, signal, sys, threading, util
10
10
11 def countcpus():
11 def countcpus():
12 '''try to count the number of CPUs on the system'''
12 '''try to count the number of CPUs on the system'''
@@ -77,6 +77,7 b' def _posixworker(ui, func, staticargs, a'
77 workers = _numworkers(ui)
77 workers = _numworkers(ui)
78 oldhandler = signal.getsignal(signal.SIGINT)
78 oldhandler = signal.getsignal(signal.SIGINT)
79 signal.signal(signal.SIGINT, signal.SIG_IGN)
79 signal.signal(signal.SIGINT, signal.SIG_IGN)
80 pids, problem = [], [0]
80 for pargs in partition(args, workers):
81 for pargs in partition(args, workers):
81 pid = os.fork()
82 pid = os.fork()
82 if pid == 0:
83 if pid == 0:
@@ -88,26 +89,40 b' def _posixworker(ui, func, staticargs, a'
88 os._exit(0)
89 os._exit(0)
89 except KeyboardInterrupt:
90 except KeyboardInterrupt:
90 os._exit(255)
91 os._exit(255)
92 pids.append(pid)
93 pids.reverse()
91 os.close(wfd)
94 os.close(wfd)
92 fp = os.fdopen(rfd, 'rb', 0)
95 fp = os.fdopen(rfd, 'rb', 0)
96 def killworkers():
97 # if one worker bails, there's no good reason to wait for the rest
98 for p in pids:
99 try:
100 os.kill(p, signal.SIGTERM)
101 except OSError, err:
102 if err.errno != errno.ESRCH:
103 raise
104 def waitforworkers():
105 for _ in pids:
106 st = _exitstatus(os.wait()[1])
107 if st and not problem:
108 problem[0] = st
109 killworkers()
110 t = threading.Thread(target=waitforworkers)
111 t.start()
93 def cleanup():
112 def cleanup():
94 # python 2.4 is too dumb for try/yield/finally
95 signal.signal(signal.SIGINT, oldhandler)
113 signal.signal(signal.SIGINT, oldhandler)
96 problem = None
114 t.join()
97 for i in xrange(workers):
115 status = problem[0]
98 pid, st = os.wait()
116 if status:
99 st = _exitstatus(st)
117 if status < 0:
100 if st and not problem:
118 os.kill(os.getpid(), -status)
101 problem = st
119 sys.exit(status)
102 if problem:
103 if problem < 0:
104 os.kill(os.getpid(), -problem)
105 sys.exit(problem)
106 try:
120 try:
107 for line in fp:
121 for line in fp:
108 l = line.split(' ', 1)
122 l = line.split(' ', 1)
109 yield int(l[0]), l[1][:-1]
123 yield int(l[0]), l[1][:-1]
110 except: # re-raises
124 except: # re-raises
125 killworkers()
111 cleanup()
126 cleanup()
112 raise
127 raise
113 cleanup()
128 cleanup()
General Comments 0
You need to be logged in to leave comments. Login now