Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions tests/test_regr1.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
import queue
import multiprocessing
import signal
import subprocess
import sys
import threading
import unittest

Expand Down Expand Up @@ -117,3 +119,32 @@ def test_issue39_regression(self):
finally:
self.running = False
signal.signal(signal.SIGALRM, signal.SIG_IGN)


class TestIssue760Regr(unittest.TestCase):
"""See https://github.com/MagicStack/uvloop/issues/760 for details.

Directly constructing uvloop.loop.Server with a loop of None isn't a
supported usage pattern, but it segfaulted instead of raising a
Python exception, since the None was only checked much later, deep
inside close(). Run the reproducer in a subprocess since a regression
here crashes the whole interpreter rather than raising.
"""

def test_server_with_none_loop_raises_instead_of_crashing(self):
code = (
"from uvloop.loop import Server\n"
"server = Server(None)\n"
"server.close()\n"
)
proc = subprocess.run(
[sys.executable, '-c', code],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)

self.assertNotEqual(
proc.returncode, -11,
f'process was killed by SIGSEGV; stderr:\n'
f'{proc.stderr.decode()}')
self.assertEqual(proc.returncode, 1)
self.assertIn(b'TypeError', proc.stderr)
2 changes: 1 addition & 1 deletion uvloop/server.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import asyncio


cdef class Server:
def __cinit__(self, Loop loop):
def __cinit__(self, Loop loop not None):
self._loop = loop
self._servers = []
self._waiters = []
Expand Down
Loading