Skip to content

Commit 85a4605

Browse files
committed
Fix another Cython bug; patch asyncio to work with Cython coroutines
1 parent e2cf018 commit 85a4605

File tree

4 files changed

+44
-0
lines changed

4 files changed

+44
-0
lines changed

Makefile

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,22 @@ src = re.sub(
101101

102102
src, flags=re.X)
103103

104+
src = re.sub(
105+
r'''
106+
\s* __Pyx_Coroutine_get_name\(__pyx_CoroutineObject\s+\*self\)
107+
\s* {
108+
\s* Py_INCREF\(self->gi_name\);
109+
''',
110+
111+
r'''
112+
__Pyx_Coroutine_get_name(__pyx_CoroutineObject *self)
113+
{
114+
if (self->gi_name == NULL) { return __pyx_empty_unicode; }
115+
Py_INCREF(self->gi_name);
116+
''',
117+
118+
src, flags=re.X)
119+
104120
with open('uvloop/loop.c', 'wt') as f:
105121
f.write(src)
106122
endef

tests/test_base.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,7 +398,13 @@ def coro():
398398
class TestBaseUV(_TestBase, UVTestCase):
399399

400400
def test_cython_coro_is_coroutine(self):
401+
from asyncio.coroutines import _format_coroutine
402+
401403
coro = self.loop.create_server(object)
404+
405+
self.assertEqual(_format_coroutine(coro),
406+
'Loop.create_server()')
407+
402408
self.assertEqual(self.loop.create_server.__qualname__,
403409
'Loop.create_server')
404410
self.assertEqual(self.loop.create_server.__name__,
@@ -411,6 +417,8 @@ def test_cython_coro_is_coroutine(self):
411417
self.loop.run_until_complete(fut)
412418
except asyncio.CancelledError:
413419
pass
420+
421+
_format_coroutine(coro) # This line checks against Cython segfault
414422
coro.close()
415423

416424

uvloop/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from asyncio.events import BaseDefaultEventLoopPolicy as __BasePolicy
44

55
from . import includes as __includes
6+
from . import _patch
67
from .loop import Loop as __BaseLoop
78

89

uvloop/_patch.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import asyncio
2+
3+
from asyncio import coroutines
4+
5+
6+
def _format_coroutine(coro):
7+
if asyncio.iscoroutine(coro) and not hasattr(coro, 'cr_code'):
8+
# Most likely a Cython coroutine
9+
coro_name = '{}()'.format(coro.__qualname__ or coro.__name__)
10+
if coro.cr_running:
11+
return '{} running'.format(coro_name)
12+
else:
13+
return coro_name
14+
15+
return _old_format_coroutine(coro)
16+
17+
18+
_old_format_coroutine = coroutines._format_coroutine
19+
coroutines._format_coroutine = _format_coroutine

0 commit comments

Comments
 (0)