From ac1688fe9bc99e6157829a3d2b649d0b0ef95d2a Mon Sep 17 00:00:00 2001 From: benoitc Date: Sat, 20 Nov 2010 12:43:46 +0100 Subject: [PATCH] fix temporary file leaking . --- gunicorn/arbiter.py | 2 -- gunicorn/workers/base.py | 15 ++++----------- gunicorn/workers/workertmp.py | 28 ++++++++++++++++++++++++++++ 3 files changed, 32 insertions(+), 13 deletions(-) create mode 100644 gunicorn/workers/workertmp.py diff --git a/gunicorn/arbiter.py b/gunicorn/arbiter.py index 4e631dc5..d6b91dd6 100644 --- a/gunicorn/arbiter.py +++ b/gunicorn/arbiter.py @@ -452,7 +452,6 @@ class Arbiter(object): try: worker.tmp.close() self.cfg.worker_exit(self, worker) - os.unlink(worker.tmpname) except: pass @@ -490,7 +489,6 @@ class Arbiter(object): worker = self.WORKERS.pop(pid) worker.tmp.close() self.cfg.worker_exit(self, worker) - os.unlink(worker.tmpname) return except (KeyError, OSError): return diff --git a/gunicorn/workers/base.py b/gunicorn/workers/base.py index 27c51617..ff1c6e0f 100644 --- a/gunicorn/workers/base.py +++ b/gunicorn/workers/base.py @@ -12,6 +12,7 @@ import sys import tempfile from gunicorn import util +from gunicorn.workers.workertmp import WorkerTmp class Worker(object): @@ -39,14 +40,10 @@ class Worker(object): self.nr = 0 self.max_requests = cfg.max_requests or sys.maxint self.alive = True - self.spinner = 0 self.log = logging.getLogger(__name__) self.debug = cfg.debug self.address = self.socket.getsockname() - - self.fd, self.tmpname = tempfile.mkstemp(prefix="wgunicorn-") - util.chown(self.tmpname, cfg.uid, cfg.gid) - self.tmp = os.fdopen(self.fd, "r+b") + self.tmp = WorkerTmp() def __str__(self): return "" % self.pid @@ -61,11 +58,7 @@ class Worker(object): once every ``self.timeout`` seconds. If you fail in accomplishing this task, the master process will murder your workers. """ - self.spinner = (self.spinner+1) % 2 - if getattr(os, 'fchmod', None): - os.fchmod(self.tmp.fileno(), self.spinner) - else: - os.chmod(self.tmpname, self.spinner) + self.tmp.notify() def run(self): """\ @@ -94,7 +87,7 @@ class Worker(object): # Prevent fd inherientence util.close_on_exec(self.socket) - util.close_on_exec(self.fd) + util.close_on_exec(self.tmp.fileno()) self.init_signals() self.wsgi = self.app.wsgi() diff --git a/gunicorn/workers/workertmp.py b/gunicorn/workers/workertmp.py new file mode 100644 index 00000000..6de282c2 --- /dev/null +++ b/gunicorn/workers/workertmp.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 - +# +# This file is part of gunicorn released under the MIT license. +# See the NOTICE for more information. + +import os +import tempfile + +class WorkerTmp(object): + + def __init__(self): + self._tmp = tempfile.TemporaryFile(prefix="wgunicorn-") + self.spinner = 0 + + def notify(self): + try: + self.spinner = (self.spinner+1) % 2 + os.fchmod(self._tmp.fileno(), self.spinner) + except AttributeError: + # python < 2.6 + self._tmp.truncate(0) + os.write(self._tmp.fileno(), "X") + + def fileno(self): + return self._tmp.fileno() + + def close(self): + return self._tmp.close()