Repository: benoitc/gunicorn

Issue:
Close File Handles on HUP Signal
This is related to https://github.com/benoitc/gunicorn/pull/624#issuecomment-25983432. Please let me know if any additional details are required, or if I can assist in some way.

I first proposed closing explicitly, but probably not the best way to do it. Another option is to hold on to the same logger object, and just update the cfg, and call reopen on it? This is probably more complicated though...

The issue was first noticed on CentOS release 6.4 (Final) x86_64 machine, it can still be reproduced on that os, it has sporadically failed on OS X 10.8:

```
$ gunicorn -c conf.py myapp:app &
[1] 18042
$ lsof -p `cat gunicorn.pid` | grep accesslog_test.txt
gunicorn 18042 avaitla    5w   REG    202,2        0     3305 /home/avaitla/gunicorn/accesslog_test.txt
$ lsof -p `cat gunicorn.pid` | grep errorlog_test.txt
gunicorn 18042 avaitla    1u   REG    202,2     2522     3304 /home/avaitla/gunicorn/errorlog_test.txt
gunicorn 18042 avaitla    2u   REG    202,2     2522     3304 /home/avaitla/gunicorn/errorlog_test.txt
gunicorn 18042 avaitla    3u   REG    202,2     2522     3304 /home/avaitla/gunicorn/errorlog_test.txt
gunicorn 18042 avaitla    4w   REG    202,2     2522     3304 /home/avaitla/gunicorn/errorlog_test.txt

$ kill -HUP `cat gunicorn.pid`
$ lsof -p `cat gunicorn.pid` | grep accesslog_test.txt
gunicorn 18042 avaitla    5w   REG    202,2        0     3305 /home/avaitla/gunicorn/accesslog_test.txt
gunicorn 18042 avaitla   15w   REG    202,2        0     3305 /home/avaitla/gunicorn/accesslog_test.txt
$ lsof -p `cat gunicorn.pid` | grep errorlog_test.txt
gunicorn 18042 avaitla    1u   REG    202,2     3145     3304 /home/avaitla/gunicorn/errorlog_test.txt
gunicorn 18042 avaitla    2u   REG    202,2     3145     3304 /home/avaitla/gunicorn/errorlog_test.txt
gunicorn 18042 avaitla    3u   REG    202,2     3145     3304 /home/avaitla/gunicorn/errorlog_test.txt
gunicorn 18042 avaitla    4w   REG    202,2     3145     3304 /home/avaitla/gunicorn/errorlog_test.txt
gunicorn 18042 avaitla   13u   REG    202,2     3145     3304 /home/avaitla/gunicorn/errorlog_test.txt
gunicorn 18042 avaitla   14w   REG    202,2     3145     3304 /home/avaitla/gunicorn/errorlog_test.txt

$ kill -HUP `cat gunicorn.pid`
$ lsof -p `cat gunicorn.pid` | grep accesslog_test.txt
gunicorn 18042 avaitla    5w   REG    202,2        0     3305 /home/avaitla/gunicorn/accesslog_test.txt
gunicorn 18042 avaitla   11u   REG    202,2        0     3305 /home/avaitla/gunicorn/accesslog_test.txt
gunicorn 18042 avaitla   15w   REG    202,2        0     3305 /home/avaitla/gunicorn/accesslog_test.txt
$ lsof -p `cat gunicorn.pid` | grep errorlog_test.txt
gunicorn 18042 avaitla    1u   REG    202,2     3768     3304 /home/avaitla/gunicorn/errorlog_test.txt
gunicorn 18042 avaitla    2u   REG    202,2     3768     3304 /home/avaitla/gunicorn/errorlog_test.txt
gunicorn 18042 avaitla    3u   REG    202,2     3768     3304 /home/avaitla/gunicorn/errorlog_test.txt
gunicorn 18042 avaitla    4w   REG    202,2     3768     3304 /home/avaitla/gunicorn/errorlog_test.txt
gunicorn 18042 avaitla    9u   REG    202,2     3768     3304 /home/avaitla/gunicorn/errorlog_test.txt
gunicorn 18042 avaitla   10u   REG    202,2     3768     3304 /home/avaitla/gunicorn/errorlog_test.txt
gunicorn 18042 avaitla   14w   REG    202,2     3768     3304 /home/avaitla/gunicorn/errorlog_test.txt
```



Discussion:
The reason I think this doesn't have to do with close_on_exec, is because the Master process doesn't get recreated when HUP signal is received, only the workers. So I am thinking that close_on_exec doesn't apply in this case, since we are dealing with the masters handles and not the workers.


Resolving patch:
diff --git a/gunicorn/arbiter.py b/gunicorn/arbiter.py
--- a/gunicorn/arbiter.py
+++ b/gunicorn/arbiter.py
@@ -56,6 +56,7 @@ def __init__(self, app):
 
         self._num_workers = None
         self._last_logged_active_worker_count = None
+        self.log = None
 
         self.setup(app)
 
@@ -88,7 +89,9 @@ def _set_num_workers(self, value):
     def setup(self, app):
         self.app = app
         self.cfg = app.cfg
-        self.log = self.cfg.logger_class(app.cfg)
+
+        if self.log is None:
+            self.log = self.cfg.logger_class(app.cfg)
 
         # reopen files
         if 'GUNICORN_FD' in os.environ:


Test patch: