internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: benoitc/gunicorn

Issue:
Can't terminate gunicorn_django via Ctrl-C in Script
I can not get Ctrl-C to stop gunicorn_django cleanly in a script.  I've outlined my problem here: http://superuser.com/questions/428486/script-wont-stop-cleanly#comment492277_428486

I've also tried stopping the script with upstart, but that doesn't stop cleanly either.  

And it seems I'm not the only one having this problem:
http://stackoverflow.com/questions/9857344/cant-terminate-gunicorn-django-via-ctrl-c-when-invoked-from-a-makefile

I'd be happy to provide additional information if needed. 



Discussion:

Resolving patch:
diff --git a/gunicorn/app/base.py b/gunicorn/app/base.py
--- a/gunicorn/app/base.py
+++ b/gunicorn/app/base.py
@@ -119,12 +119,7 @@ def run(self):
             debug.spew()
         if self.cfg.daemon:
             util.daemonize()
-        else:
-            try:
-                os.setpgrp()
-            except OSError, e:
-                if e[0] != errno.EPERM:
-                    raise
+
         try:
             Arbiter(self).run()
         except RuntimeError, e:


Test patch:
Repository: benoitc/gunicorn

Issue:
Duplicate init_process method in EventletWorker
There are two init_process methods in the EventletWorker. See:
https://github.com/olt/gunicorn/blob/master/gunicorn/workers/geventlet.py#L48
https://github.com/olt/gunicorn/blob/master/gunicorn/workers/geventlet.py#L91



Discussion:
Thanks! Maybe you also want to send a PR/patch fixing the problem? If not will make it myself asap.

I don't know which one is the right. :-)
Is `hubs.use_hub()` required and if, does it need to come before or after `patch()`?

hah :) `hubs.use_hub()` should come before `self.patch` . both need to be
there if I remember well

On Mon, Dec 9, 2013 at 10:18 AM, Oliver Tonnhofer
notifications@github.comwrote:

> I don't know which one is the right. :-)
> Is hubs.use_hub() required and if, does it need to come before or after
> patch()?
> 
> —
> Reply to this email directly or view it on GitHubhttps://github.com/benoitc/gunicorn/issues/657#issuecomment-30116606
> .


Resolving patch:
diff --git a/gunicorn/workers/geventlet.py b/gunicorn/workers/geventlet.py
--- a/gunicorn/workers/geventlet.py
+++ b/gunicorn/workers/geventlet.py
@@ -47,6 +47,7 @@ def patch(self):
 
     def init_process(self):
         hubs.use_hub()
+        self.patch()
         super(EventletWorker, self).init_process()
 
     def timeout_ctx(self):
@@ -87,8 +88,3 @@ def run(self):
             if te != t:
                 raise
             [a.kill() for a in acceptors]
-
-    def init_process(self):
-        # monkey patch here
-        self.patch()
-        super(EventletWorker, self).init_process()


Test patch:
Repository: benoitc/gunicorn

Issue:
Fix utils.is_fileobj for streaming responses from requests
Turns out that the utils.is_fileobj breaks for streamed responses from the requests library due to how we check for a fileno() function and the exception raised by urllib3.

https://github.com/benoitc/gunicorn/blob/19.0/gunicorn/util.py#L511-L521
https://github.com/kennethreitz/requests/blob/v2.3.0/requests/packages/urllib3/response.py#L294-L301

Obvious fix is to add the IOError type to the exception list. PR to follow shortly.



Discussion:

Resolving patch:
diff --git a/gunicorn/util.py b/gunicorn/util.py
--- a/gunicorn/util.py
+++ b/gunicorn/util.py
@@ -515,7 +515,7 @@ def is_fileobject(obj):
     # check BytesIO case and maybe others
     try:
         obj.fileno()
-    except io.UnsupportedOperation:
+    except (IOError, io.UnsupportedOperation):
         return False
 
     return True


Test patch:
Repository: benoitc/gunicorn

Issue:
Upcoming Tornado change breaks gunicorn.workers.gtornado
The next release of Tornado (will be 4.0 when released, although the current master branch hasn't been updated to change all mentions of 3.3 to 4.0) makes some major changes to the HTTP internals and breaks gunicorn's monkey-patching of HTTPConnection.finish.  Fortunately, there is now a cleaner way to do the tracking that gunicorn wants to do here, since the interface between HTTPServer and Application is more formally defined by the HTTPServerConnectionDelegate and HTTPMessageDelegate interfaces, so you should be able to wrap the Application (which implements/subclasses HTTPServerConnectionDelegate) and the HTTPMessageDelegate its start_request method returns.  



Discussion:
Thanks, @bdarnell. Since you're familiar with these changes, do you think you could write a patch?

I've never actually used gunicorn and it doesn't look like there is any unit test coverage of this module, so I'm probably not the best person to make this change.

@bdarnell thanks! I will make sure the worker is working for the next release. Any idea when the 4.0 will be out?

I'm going to release a beta of 4.0 within a couple of weeks.

I apologize for forgetting to ping this thread again, but Tornado 4.0 was just released today.

@bdarnell thanks, should be fixed with  a release today, I'm working on it :)


Resolving patch:
diff --git a/gunicorn/workers/gtornado.py b/gunicorn/workers/gtornado.py
--- a/gunicorn/workers/gtornado.py
+++ b/gunicorn/workers/gtornado.py
@@ -68,20 +68,31 @@ def run(self):
         # will help gunicorn shutdown the worker if max_requests
         # is exceeded.
         httpserver = sys.modules["tornado.httpserver"]
-        old_connection_finish = httpserver.HTTPConnection.finish
+        if hasattr(httpserver, 'HTTPConnection'):
+            old_connection_finish = httpserver.HTTPConnection.finish
 
-        def finish(other):
-            self.handle_request()
-            old_connection_finish(other)
-        httpserver.HTTPConnection.finish = finish
-        sys.modules["tornado.httpserver"] = httpserver
+            def finish(other):
+                self.handle_request()
+                old_connection_finish(other)
+            httpserver.HTTPConnection.finish = finish
+            sys.modules["tornado.httpserver"] = httpserver
+
+            server_class = tornado.httpserver.HTTPServer
+        else:
+
+            class _HTTPServer(tornado.httpserver.HTTPServer):
+
+                def on_close(instance, server_conn):
+                    self.handle_request()
+                    super(_HTTPServer, instance).on_close(server_conn)
+
+            server_class = _HTTPServer
 
         if self.cfg.is_ssl:
-            server = tornado.httpserver.HTTPServer(app, io_loop=self.ioloop,
+            server = server_class(app, io_loop=self.ioloop,
                     ssl_options=self.cfg.ssl_options)
         else:
-            server = tornado.httpserver.HTTPServer(app,
-                    io_loop=self.ioloop)
+            server = server_class(app, io_loop=self.ioloop)
 
         self.server = server
 


Test patch:
Repository: benoitc/gunicorn

Issue:
Gunicorn 19.1 seems to ignore --logger-class because the stats_host config is set by default
The --stats-host config seem to be populated with a default value of localhost:8125 (config.py:1650)

This will make the logger_class code load the stats logger by default instead of the provided --logger-class.

I don't see any way to disable the default or pass some kind of null value to --stats-hosts.



Discussion:
Oh, that's no good. We'll have to fix this and put out a bugfix release.
A thought when I reviewed the statsd stuff that it would be overridden by logger class.
I'll check again. Marking this for the next release.

@alq666 could you take a look?

@tilgovi will do


Resolving patch:
diff --git a/gunicorn/config.py b/gunicorn/config.py
--- a/gunicorn/config.py
+++ b/gunicorn/config.py
@@ -142,9 +142,9 @@ def logger_class(self):
         if uri == "simple":
             # support the default
             uri = "gunicorn.glogging.Logger"
-        
+
         # if statsd is on, automagically switch to the statsd logger
-        if 'statsd_host' in self.settings:
+        if 'statsd_host' in self.settings and self.settings['statsd_host'].value is not None:
             logger_class = util.load_class("gunicorn.instrument.statsd.Statsd",
                 section="gunicorn.loggers")
         else:
@@ -1646,7 +1646,7 @@ class StatsdHost(Setting):
     section = "Logging"
     cli = ["--statsd-host"]
     meta = "STATSD_ADDR"
-    default = "localhost:8125"
+    default = None
     validator = validate_hostport
     desc ="""\
     host:port of the statsd server to log to


Test patch:
Repository: benoitc/gunicorn

Issue:
documment the way the settings.rst file is built
I noticed that some some people are editing the file `settings.rst` where only `settings.py` should be updated since the doc is built from it. We should make it clear somewhere in the doc.



Discussion:
see 7f0c7c56e346597ab99e7183892032b45cb90fdb for an example.


Resolving patch:
diff --git a/gunicorn/config.py b/gunicorn/config.py
--- a/gunicorn/config.py
+++ b/gunicorn/config.py
@@ -3,6 +3,8 @@
 # This file is part of gunicorn released under the MIT license.
 # See the NOTICE for more information.
 
+# Please remember to run "make -C docs html" after update "desc" attributes.
+
 import copy
 import grp
 import inspect
@@ -457,7 +459,6 @@ def get_default_config_file():
     return None
 
 
-# Please remember to run "make html" in docs/ after update "desc" attributes.
 class ConfigFile(Setting):
     name = "config"
     section = "Config File"


Test patch:
Repository: benoitc/gunicorn

Issue:
proxy protocol info lost after first keep-alive request
env:
- python v2.7
- gunicorn v19.1.1
- gevent v1.0.1 worker type
- keep-alive proxy-protcol'd lb (aws elb) in front of gunicorn

for multiple reqs during keep-alive session:
- first parses `req.proxy_protocol_info`
- subsequent reqs do not
  so workers see only proxy network info (`REMOTE_ADDR`, `REMOTE_PORT` ).

probably should save off from 1st and propagate to later requests.

proxy protocol info lost after first keep-alive request
env:
- python v2.7
- gunicorn v19.1.1
- gevent v1.0.1 worker type
- keep-alive proxy-protcol'd lb (aws elb) in front of gunicorn

for multiple reqs during keep-alive session:
- first parses `req.proxy_protocol_info`
- subsequent reqs do not
  so workers see only proxy network info (`REMOTE_ADDR`, `REMOTE_PORT` ).

probably should save off from 1st and propagate to later requests.



Discussion:

Resolving patch:
diff --git a/gunicorn/workers/async.py b/gunicorn/workers/async.py
--- a/gunicorn/workers/async.py
+++ b/gunicorn/workers/async.py
@@ -38,12 +38,14 @@ def handle(self, listener, client, addr):
                     self.handle_request(listener_name, req, client, addr)
                 else:
                     # keepalive loop
+                    proxy_protocol_info = req.proxy_protocol_info
                     while True:
                         req = None
                         with self.timeout_ctx():
                             req = six.next(parser)
                         if not req:
                             break
+                        req.proxy_protocol_info = proxy_protocol_info
                         self.handle_request(listener_name, req, client, addr)
             except http.errors.NoMoreData as e:
                 self.log.debug("Ignored premature client disconnection. %s", e)


Test patch:
Repository: benoitc/gunicorn

Issue:
Option `--debug` 's help is outdate 
Option `--debug` is fake while its help doesn't show that.

We decide to remove option `--debug` completely in v20, see #915 



Discussion:

Resolving patch:
diff --git a/examples/example_config.py b/examples/example_config.py
--- a/examples/example_config.py
+++ b/examples/example_config.py
@@ -75,14 +75,6 @@
 timeout = 30
 keepalive = 2
 
-#
-# Debugging
-#
-#   debug - Turn on debugging in the server. This limits the number of
-#       worker processes to 1 and changes some error handling that's
-#       sent to clients.
-#
-#       True or False
 #
 #   spew - Install a trace function that spews every line of Python
 #       that is executed when running the server. This is the
@@ -91,7 +83,6 @@
 #       True or False
 #
 
-debug = False
 spew = False
 
 #
diff --git a/gunicorn/config.py b/gunicorn/config.py
--- a/gunicorn/config.py
+++ b/gunicorn/config.py
@@ -755,21 +755,6 @@ class LimitRequestFieldSize(Setting):
         """
 
 
-class Debug(Setting):
-    name = "debug"
-    section = "Debugging"
-    cli = ["--debug"]
-    validator = validate_bool
-    action = "store_true"
-    default = False
-    desc = """\
-        Turn on debugging in the server.
-
-        **DEPRECATED**: This no functionality was removed after v18.0.
-        This option is now a no-op.
-        """
-
-
 class Reload(Setting):
     name = "reload"
     section = 'Debugging'


Test patch:
Repository: benoitc/gunicorn

Issue:
Include request URL in error message
It would be really helpful if the logged error message were "Error handling request http://host/path/etc" instead of just "Error handling request".



Discussion:
Agreed. Open a PR with this change for each worker and I would be glad to merge it.


Resolving patch:
diff --git a/gunicorn/workers/base.py b/gunicorn/workers/base.py
--- a/gunicorn/workers/base.py
+++ b/gunicorn/workers/base.py
@@ -210,7 +210,7 @@ def handle_error(self, req, client, addr, exc):
             msg = "Invalid request from ip={ip}: {error}"
             self.log.debug(msg.format(ip=addr[0], error=str(exc)))
         else:
-            self.log.exception("Error handling request")
+            self.log.exception("Error handling request %s", req.uri)
 
             status_int = 500
             reason = "Internal Server Error"


Test patch:
Repository: benoitc/gunicorn

Issue:
Correctly handle unavailable .fileno() support for io.BytesIO instances
The changes introduced in https://github.com/benoitc/gunicorn/commit/98c9e3b3756717771fd6521dbb2dbec206ec5fc5#diff-6607b435d6ee868f251dbdd1a6d0edecL357 are wrong and lead to crashes for `io.BytesIO` instances which do have a `.fileno()` method but raise another exception instead:

```
>>> import io
>>> io.BytesIO().fileno()
Traceback (most recent call last):
  File "<ipython-input-3-7062c09d0c52>", line 1, in <module>
    io.BytesIO().fileno()
UnsupportedOperation: fileno
```

This exception was already caught properly in the earlier code, a few lines below.



Discussion:
I guess this is a critical bug since it breaks a lot of cases like `flask.send_file()` (and other frameworks with similar features) with a `io.BytesIO()` instance, which is a rather common pattern.


Resolving patch:
diff --git a/gunicorn/http/wsgi.py b/gunicorn/http/wsgi.py
--- a/gunicorn/http/wsgi.py
+++ b/gunicorn/http/wsgi.py
@@ -353,9 +353,7 @@ def sendfile(self, respiter):
         if self.cfg.is_ssl or not self.can_sendfile():
             return False
 
-        try:
-            fileno = respiter.filelike.fileno()
-        except AttributeError:
+        if not util.has_fileno(respiter.filelike):
             return False
 
         try:
diff --git a/gunicorn/util.py b/gunicorn/util.py
--- a/gunicorn/util.py
+++ b/gunicorn/util.py
@@ -510,14 +510,14 @@ def to_bytestring(value, encoding="utf8"):
 
     return value.encode(encoding)
 
-def is_fileobject(obj):
-    if not hasattr(obj, "tell") or not hasattr(obj, "fileno"):
+def has_fileno(obj):
+    if not hasattr(obj, "fileno"):
         return False
 
     # check BytesIO case and maybe others
     try:
         obj.fileno()
-    except (IOError, io.UnsupportedOperation):
+    except (AttributeError, IOError, io.UnsupportedOperation):
         return False
 
     return True


Test patch:
Repository: benoitc/gunicorn

Issue:
Error in log message when changing listeners on reload
When arbiter reloads workers on SIGHUP, and if old address is different from new address, it creates new sockets and logs about that. (https://github.com/benoitc/gunicorn/blob/master/gunicorn/arbiter.py#L402)

```
self.log.info("Listening at: %s", ",".join(str(self.LISTENERS)))
```

it takes a `list`, converts it to `str` and then joins resulting string with `,`. Resulting log message is as follows:

```
[INFO] Listening at: [,<,g,u,n,i,c,o,r,n,.,s,o,c,k,.,T,C,P,S,o,c,k,e,t, ,o,b,j,e,c,t, ,a,t, ,0,x,7,f,8,e,3,d,2,1,f,7,8,0,>,]
```

Seems that this line should look like this:

```
self.log.info("Listening at: %s", ",".join(map(str, self.LISTENERS)))
```

Or maybe it should be made like on line 132 (in `Arbiter.start`).



Discussion:

Resolving patch:
diff --git a/gunicorn/arbiter.py b/gunicorn/arbiter.py
--- a/gunicorn/arbiter.py
+++ b/gunicorn/arbiter.py
@@ -399,7 +399,8 @@ def reload(self):
             [l.close() for l in self.LISTENERS]
             # init new listeners
             self.LISTENERS = create_sockets(self.cfg, self.log)
-            self.log.info("Listening at: %s", ",".join(str(self.LISTENERS)))
+            listeners_str = ",".join([str(l) for l in self.LISTENERS])
+            self.log.info("Listening at: %s", listeners_str)
 
         # do some actions on reload
         self.cfg.on_reload(self)


Test patch:
Repository: benoitc/gunicorn

Issue:
socket is not registered: gthread worker crash
I'm using gunicorn 19.4.1, and I haven't been able to figure out how to reproduce this reliably, but I'm seeing the following crash periodically in my gthread workers. This causes the worker to exit and the master to spawn a new one. I also found the following StackOverflow question that mentions running into the same problem: http://stackoverflow.com/questions/26634327/gunicorn-worker-periodically-crashes-socket-is-not-registered

The workaround in that question suggests that the issue could be related to keepalive and connections that were timed out. I could believe that might be related: I seem to hit the issue when my workers are extremely busy.

I will report back if I figure out more details.

Stack trace:

```
Traceback (most recent call last):
  File "/env/local/lib/python2.7/site-packages/gunicorn/arbiter.py", line 515, in spawn_worker
    worker.init_process()
  File "/env/local/lib/python2.7/site-packages/gunicorn/workers/gthread.py", line 109, in init_process
    super(ThreadWorker, self).init_process()
  File "/env/local/lib/python2.7/site-packages/gunicorn/workers/base.py", line 126, in init_process
    self.run()
  File "/env/local/lib/python2.7/site-packages/gunicorn/workers/gthread.py", line 217, in run
    self.murder_keepalived()
  File "/env/local/lib/python2.7/site-packages/gunicorn/workers/gthread.py", line 178, in murder_keepalived
    self.poller.unregister(conn.sock)
  File "/env/local/lib/python2.7/site-packages/gunicorn/selectors.py", line 409, in unregister
    key = super(EpollSelector, self).unregister(fileobj)
  File "/env/local/lib/python2.7/site-packages/gunicorn/selectors.py", line 244, in unregister
    raise KeyError("{0!r} is not registered".format(fileobj))
KeyError: '<socket._socketobject object at 0x7f84e19e7de0> is not registered'
```

For completeness: I initially reported this on Google App Engine's issue tracker: https://github.com/GoogleCloudPlatform/python-compat-runtime/issues/94



Discussion:

Resolving patch:
diff --git a/gunicorn/workers/gthread.py b/gunicorn/workers/gthread.py
--- a/gunicorn/workers/gthread.py
+++ b/gunicorn/workers/gthread.py
@@ -179,6 +179,9 @@ def murder_keepalived(self):
                     except EnvironmentError as e:
                         if e.errno != errno.EBADF:
                             raise
+                    except KeyError:
+                        # already removed by the system, continue
+                        pass
 
                 # close the socket
                 conn.close()


Test patch:
Repository: benoitc/gunicorn

Issue:
Supporting newest version of python
Gunicorn currently doesn't run tests with python3.6.

Since 3.6 is release and some of us are preparing to use it in production it would be great if gunicorn had confirmed support.

Also `setup.py` classifiers doesn't include 3.5 or 3.6.


Discussion:
Thanks for the report. Could you share which tests are broken?
I assume none are actually broken, I would assume it's as simple as adding python3.6 to tox?

(Unless of course you take the "if it's not tested, it's broken" approach, in which case they all are :smile:)
I just ran tests with my CPython copy (3.7.0a0) and they all passed so you're right :) We just need to update tox.ini, .travis.yml and setup.py.

(Glad to see someone's planning to use Python 3.6 in production :))
Personally I have

```yaml
python:
- '3.5'
- '3.6'
- '3.6-dev'
- 'nightly'

matrix:
  allow_failures:
  - python: '3.6-dev'
  - python: 'nightly'
```

For example [here](https://github.com/samuelcolvin/arq/blob/master/.travis.yml) so I know when future version of python are breaking. I assume you could setup the same thing with tox?

Resolving patch:
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -27,6 +27,8 @@
     'Programming Language :: Python :: 3.2',
     'Programming Language :: Python :: 3.3',
     'Programming Language :: Python :: 3.4',
+    'Programming Language :: Python :: 3.5',
+    'Programming Language :: Python :: 3.6',
     'Topic :: Internet',
     'Topic :: Utilities',
     'Topic :: Software Development :: Libraries :: Python Modules',


Test patch:
Repository: benoitc/gunicorn

Issue:
Make "failed to find application" a bit more informative
When issuing `gunicorn myapp:app` and obtaining result `failed to find application myapp`, it would be better if it was clear whether there was a problem with `myapp` or with `app`. 


Discussion:

Resolving patch:
diff --git a/gunicorn/util.py b/gunicorn/util.py
--- a/gunicorn/util.py
+++ b/gunicorn/util.py
@@ -363,7 +363,7 @@ def import_app(module):
     except NameError:
         if is_debug:
             traceback.print_exception(*sys.exc_info())
-        raise AppImportError("Failed to find application: %r" % module)
+        raise AppImportError("Failed to find application object %r in %r" % (obj, module))
 
     if app is None:
         raise AppImportError("Failed to find application object: %r" % obj)


Test patch:
diff --git a/tests/support.py b/tests/support.py
--- a/tests/support.py
+++ b/tests/support.py
@@ -2,10 +2,26 @@
 import sys
 import unittest
 import platform
+from wsgiref.validate import validator
 
 HOST = "127.0.0.1"
 
 
+@validator
+def app(environ, start_response):
+    """Simplest possible application object"""
+
+    data = b'Hello, World!\n'
+    status = '200 OK'
+
+    response_headers = [
+        ('Content-type', 'text/plain'),
+        ('Content-Length', str(len(data))),
+    ]
+    start_response(status, response_headers)
+    return iter([data])
+
+
 def requires_mac_ver(*min_version):
     """Decorator raising SkipTest if the OS is Mac OS X and the OS X
     version if less than min_version.
diff --git a/tests/test_util.py b/tests/test_util.py
--- a/tests/test_util.py
+++ b/tests/test_util.py
@@ -6,6 +6,7 @@
 import pytest
 
 from gunicorn import util
+from gunicorn.errors import AppImportError
 
 
 @pytest.mark.parametrize('test_input, expected', [
@@ -45,3 +46,16 @@ def test_warn(capsys):
     util.warn('test warn')
     _, err = capsys.readouterr()
     assert '!!! WARNING: test warn' in err
+
+
+def test_import_app():
+    assert util.import_app('support:app')
+
+    with pytest.raises(ImportError) as err:
+        util.import_app('a:app')
+    assert 'No module' in str(err)
+
+    with pytest.raises(AppImportError) as err:
+        util.import_app('support:wrong_app')
+    msg = "Failed to find application object 'wrong_app' in 'support'"
+    assert msg in str(err)