diff --git a/gunicorn/app/wsgiapp.py b/gunicorn/app/wsgiapp.py index c4911a2f..632fdcf7 100644 --- a/gunicorn/app/wsgiapp.py +++ b/gunicorn/app/wsgiapp.py @@ -22,9 +22,4 @@ class WSGIApplication(Application): sys.path.insert(0, os.getcwd()) def load(self): - try: - return util.import_app(self.app_uri) - except: - print "Failed to import application: %s" % self.app_uri - traceback.print_exc() - sys.exit(1) + return util.import_app(self.app_uri) diff --git a/gunicorn/arbiter.py b/gunicorn/arbiter.py index ddf32f75..5976357c 100644 --- a/gunicorn/arbiter.py +++ b/gunicorn/arbiter.py @@ -24,7 +24,12 @@ class Arbiter(object): kills them if needed. It also manages application reloading via SIGHUP/USR2. """ - + + # A flag indicating if a worker failed to + # to boot. If a worker process exist with + # this error code, the arbiter will terminate. + WORKER_BOOT_ERROR = 3 + START_CTX = {} LISTENER = None @@ -322,10 +327,16 @@ class Arbiter(object): try: while True: wpid, status = os.waitpid(-1, os.WNOHANG) - if not wpid: break + if not wpid: + break if self.reexec_pid == wpid: self.reexec_pid = 0 else: + # A worker said it cannot boot. We'll shutdown + # to avoid infinite start/stop cycles. + exitcode = status >> 8 + if exitcode == self.WORKER_BOOT_ERROR: + raise StopIteration worker = self.WORKERS.pop(wpid, None) if not worker: continue @@ -380,7 +391,9 @@ class Arbiter(object): except SystemExit: raise except: - self.log.exception("Exception in worker process.") + self.log.exception("Exception in worker process:") + if not worker.booted: + sys.exit(self.WORKER_BOOT_ERROR) sys.exit(-1) finally: self.log.info("Worker exiting (pid: %s)" % worker_pid) diff --git a/gunicorn/workers/base.py b/gunicorn/workers/base.py index 5bd31ea9..cf2d52d4 100644 --- a/gunicorn/workers/base.py +++ b/gunicorn/workers/base.py @@ -33,7 +33,8 @@ class Worker(object): self.app = app self.timeout = timeout self.cfg = cfg - + self.booted = False + self.nr = 0 self.alive = True self.spinner = 0 @@ -94,6 +95,7 @@ class Worker(object): self.wsgi = self.app.wsgi() # Enter main run loop + self.booted = True self.run() def init_signals(self):