#5 Add patch to restore compatibility with RHEL 8's gevent
Merged a month ago by carlwgeorge. Opened a month ago by carlwgeorge.
rpms/ carlwgeorge/python-gunicorn epel8-gevent  into  epel8

@@ -1,14 +1,17 @@ 

- From 4bf056a23856dab615cad7cb8707956e5b2a6598 Mon Sep 17 00:00:00 2001

+ From ed9d871e203be9c9a0c7dfd2d71e5290335373a0 Mon Sep 17 00:00:00 2001

  From: Dan Callaghan <dcallagh@redhat.com>

  Date: Wed, 2 Jan 2013 11:48:54 +1000

- Subject: [PATCH 1/2] use /dev/log for syslog

+ Subject: [PATCH 1/3] use /dev/log for syslog

  

+ ---

+  gunicorn/config.py | 2 +-

+  1 file changed, 1 insertion(+), 1 deletion(-)

  

  diff --git a/gunicorn/config.py b/gunicorn/config.py

- index aa97894..98e7783 100644

+ index f21f74f8..0db1a311 100644

  --- a/gunicorn/config.py

  +++ b/gunicorn/config.py

- @@ -1367,7 +1367,7 @@ class SyslogTo(Setting):

+ @@ -1394,7 +1394,7 @@ class SyslogTo(Setting):

           default = "unix:///var/run/syslog"

       elif PLATFORM in ('freebsd', 'dragonfly', ):

           default = "unix:///var/run/log"
@@ -18,5 +21,5 @@ 

       else:

           default = "udp://localhost:514"

  -- 

- 2.17.1

+ 2.41.0

  

@@ -0,0 +1,141 @@ 

+ From d5ce78c2440c3c27f3369c7b5c7c787ec1aa0cd5 Mon Sep 17 00:00:00 2001

+ From: Carl George <carl@george.computer>

+ Date: Thu, 31 Aug 2023 15:57:22 -0500

+ Subject: [PATCH 2/3] Restore compatibility with older gevent

+ 

+ Upstream added a runtime check for gevent 1.4 in gunicorn 20.0.0.

+ However, they didn't enforce this minimum version at install time in

+ setup.py until gunicorn 20.1.0.  This resulted in gunicorn 20.0.4 being

+ added to EPEL 8, even though RHEL 8 only has gevent 1.2.2.  This commit

+ removes that runtime check and the other corresponding changes so that

+ gunicorn 20.0.4 works with gevent 1.2.2.

+ 

+ Partially revert "Bump minimum Eventlet and Gevent versions (#1962)"

+ 

+ This partially reverts commit 9f87c88819b901d4cd8ddf6c2bba1198b68903cb.

+ ---

+  gunicorn/config.py          |  2 +-

+  gunicorn/workers/ggevent.py | 61 ++++++++++++++++++++++++++++---------

+  2 files changed, 48 insertions(+), 15 deletions(-)

+ 

+ diff --git a/gunicorn/config.py b/gunicorn/config.py

+ index 0db1a311..2ef1776d 100644

+ --- a/gunicorn/config.py

+ +++ b/gunicorn/config.py

+ @@ -641,7 +641,7 @@ class WorkerClass(Setting):

+          * ``sync``

+          * ``eventlet`` - Requires eventlet >= 0.24.1 (or install it via

+            ``pip install gunicorn[eventlet]``)

+ -        * ``gevent``   - Requires gevent >= 1.4 (or install it via

+ +        * ``gevent``   - Requires gevent >= 0.13 (or install it via

+            ``pip install gunicorn[gevent]``)

+          * ``tornado``  - Requires tornado >= 0.2 (or install it via

+            ``pip install gunicorn[tornado]``)

+ diff --git a/gunicorn/workers/ggevent.py b/gunicorn/workers/ggevent.py

+ index 85418035..b0d158d2 100644

+ --- a/gunicorn/workers/ggevent.py

+ +++ b/gunicorn/workers/ggevent.py

+ @@ -10,18 +10,20 @@ from datetime import datetime

+  from functools import partial

+  import time

+  

+ +_socket = __import__("socket")

+ +

+ +# workaround on osx, disable kqueue

+ +if sys.platform == "darwin":

+ +    os.environ['EVENT_NOKQUEUE'] = "1"

+ +

+  try:

+      import gevent

+  except ImportError:

+ -    raise RuntimeError("gevent worker requires gevent 1.4 or higher")

+ -else:

+ -    from pkg_resources import parse_version

+ -    if parse_version(gevent.__version__) < parse_version('1.4'):

+ -        raise RuntimeError("gevent worker requires gevent 1.4 or higher")

+ -

+ +    raise RuntimeError("You need gevent installed to use this worker.")

+  from gevent.pool import Pool

+  from gevent.server import StreamServer

+ -from gevent import hub, monkey, socket, pywsgi

+ +from gevent.socket import wait_write, socket

+ +from gevent import pywsgi

+  

+  import gunicorn

+  from gunicorn.http.wsgi import base_environ

+ @@ -36,7 +38,7 @@ def _gevent_sendfile(fdout, fdin, offset, nbytes, _os_sendfile=os.sendfile):

+              return _os_sendfile(fdout, fdin, offset, nbytes)

+          except OSError as e:

+              if e.args[0] == errno.EAGAIN:

+ -                socket.wait_write(fdout)

+ +                wait_write(fdout)

+              else:

+                  raise

+  

+ @@ -50,7 +52,14 @@ class GeventWorker(AsyncWorker):

+      wsgi_handler = None

+  

+      def patch(self):

+ -        monkey.patch_all()

+ +        from gevent import monkey

+ +        monkey.noisy = False

+ +

+ +        # if the new version is used make sure to patch subprocess

+ +        if gevent.version_info[0] == 0:

+ +            monkey.patch_all()

+ +        else:

+ +            monkey.patch_all(subprocess=True)

+  

+          # monkey patch sendfile to make it none blocking

+          patch_sendfile()

+ @@ -58,7 +67,7 @@ class GeventWorker(AsyncWorker):

+          # patch sockets

+          sockets = []

+          for s in self.sockets:

+ -            sockets.append(socket.socket(s.FAMILY, socket.SOCK_STREAM,

+ +            sockets.append(socket(s.FAMILY, _socket.SOCK_STREAM,

+                  fileno=s.sock.fileno()))

+          self.sockets = sockets

+  

+ @@ -156,10 +165,34 @@ class GeventWorker(AsyncWorker):

+          # by deferring to a new greenlet. See #1645

+          gevent.spawn(super().handle_usr1, sig, frame)

+  

+ -    def init_process(self):

+ -        self.patch()

+ -        hub.reinit()

+ -        super().init_process()

+ +    if gevent.version_info[0] == 0:

+ +

+ +        def init_process(self):

+ +            # monkey patch here

+ +            self.patch()

+ +

+ +            # reinit the hub

+ +            import gevent.core

+ +            gevent.core.reinit()

+ +

+ +            #gevent 0.13 and older doesn't reinitialize dns for us after forking

+ +            #here's the workaround

+ +            gevent.core.dns_shutdown(fail_requests=1)

+ +            gevent.core.dns_init()

+ +            super(GeventWorker, self).init_process()

+ +

+ +    else:

+ +

+ +        def init_process(self):

+ +            # monkey patch here

+ +            self.patch()

+ +

+ +            # reinit the hub

+ +            from gevent import hub

+ +            hub.reinit()

+ +

+ +            # then initialize the process

+ +            super(GeventWorker, self).init_process()

+  

+  

+  class GeventResponse(object):

+ -- 

+ 2.41.0

+ 

@@ -0,0 +1,59 @@ 

+ From ef79e6af6b44e9933c6e4973f8140ed6b3b6bee2 Mon Sep 17 00:00:00 2001

+ From: Jason Madden <jamadden@gmail.com>

+ Date: Sat, 4 Jan 2020 06:31:25 -0600

+ Subject: [PATCH 3/3] Add tests for geventlet and ggevent workers

+ 

+ (partially cherry picked from commit 2d40e6daceb9735d27bb91d9c32743695de8e01c)

+ ---

+  requirements_test.txt           | 2 ++

+  tests/workers/__init__.py       | 0

+  tests/workers/test_geventlet.py | 7 +++++++

+  tests/workers/test_ggevent.py   | 7 +++++++

+  4 files changed, 16 insertions(+)

+  create mode 100644 tests/workers/__init__.py

+  create mode 100644 tests/workers/test_geventlet.py

+  create mode 100644 tests/workers/test_ggevent.py

+ 

+ diff --git a/requirements_test.txt b/requirements_test.txt

+ index cc595b77..03af4969 100644

+ --- a/requirements_test.txt

+ +++ b/requirements_test.txt

+ @@ -1,4 +1,6 @@

+  aiohttp

+ +gevent

+ +eventlet

+  coverage

+  pytest

+  pytest-cov

+ diff --git a/tests/workers/__init__.py b/tests/workers/__init__.py

+ new file mode 100644

+ index 00000000..e69de29b

+ diff --git a/tests/workers/test_geventlet.py b/tests/workers/test_geventlet.py

+ new file mode 100644

+ index 00000000..815dcec3

+ --- /dev/null

+ +++ b/tests/workers/test_geventlet.py

+ @@ -0,0 +1,7 @@

+ +# -*- coding: utf-8 -

+ +#

+ +# This file is part of gunicorn released under the MIT license.

+ +# See the NOTICE for more information.

+ +

+ +def test_import():

+ +    __import__('gunicorn.workers.geventlet')

+ diff --git a/tests/workers/test_ggevent.py b/tests/workers/test_ggevent.py

+ new file mode 100644

+ index 00000000..261ce40d

+ --- /dev/null

+ +++ b/tests/workers/test_ggevent.py

+ @@ -0,0 +1,7 @@

+ +# -*- coding: utf-8 -

+ +#

+ +# This file is part of gunicorn released under the MIT license.

+ +# See the NOTICE for more information.

+ +

+ +def test_import():

+ +    __import__('gunicorn.workers.ggevent')

+ -- 

+ 2.41.0

+ 

file modified
+13 -3
@@ -3,13 +3,18 @@ 

  

  Name:           python-%{upstream_name}

  Version:        20.0.4

- Release:        2%{?dist}

+ Release:        3%{?dist}

  Summary:        Python WSGI application server

  License:        MIT

  URL:            http://gunicorn.org/

  Source0:        %pypi_source %{upstream_name}

  # distro-specific, not upstreamable

  Patch101:       0001-use-dev-log-for-syslog.patch

+ # restore compatibility with RHEL 8's gevent

+ Patch102:       0002-Restore-compatibility-with-older-gevent.patch

+ # partial backport of upstream commit to test the workers are importable

+ # https://github.com/benoitc/gunicorn/commit/2d40e6daceb9735d27bb91d9c32743695de8e01c

+ Patch103:       0003-Add-tests-for-geventlet-and-ggevent-workers.patch

  BuildArch:      noarch

  

  %description
@@ -23,6 +28,8 @@ 

  BuildRequires:  python3-devel

  BuildRequires:  python3-setuptools

  BuildRequires:  python3-pytest

+ BuildRequires:  python3-eventlet

+ BuildRequires:  python3-gevent

  BuildRequires:  python3-sphinx

  BuildRequires:  python3-sphinx_rtd_theme

  Requires:       python3-setuptools
@@ -40,8 +47,7 @@ 

  Documentation for the %{name} package.

  

  %prep

- %setup -q -n %{upstream_name}-%{version}

- %patch101 -p1

+ %autosetup -p 1 -n %{upstream_name}-%{version}

  sed -e '/addopts/d' -i setup.cfg

  

  %build
@@ -70,6 +76,10 @@ 

  %doc build/sphinx/html/*

  

  %changelog

+ * Thu Aug 31 2023 Carl George <carlwgeorge@fedoraproject.org> - 20.0.4-3

+ - Restore compatibility with RHEL 8's gevent, resolves rhbz#2234825

+ - Backport worker tests from upstream

+ 

  * Thu Jan 30 2020 Fedora Release Engineering <releng@fedoraproject.org> - 20.0.4-2

  - Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild