Skip to content

Commit 7b0b195

Browse files
committed
Revert "Don't use dynamic memory allocation for libuv handles/requests"
This reverts commit 6ebd07d.
1 parent 2b060e1 commit 7b0b195

24 files changed

+113
-65
lines changed

uvloop/dns.pyx

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,6 @@ cdef class AddrInfo:
224224

225225
cdef class AddrInfoRequest(UVRequest):
226226
cdef:
227-
uv.uv_getaddrinfo_t _req_data
228227
system.addrinfo hints
229228
object callback
230229

@@ -261,7 +260,12 @@ cdef class AddrInfoRequest(UVRequest):
261260
self.hints.ai_socktype = type
262261
self.hints.ai_protocol = proto
263262

264-
self.request = <uv.uv_req_t*>&self._req_data
263+
self.request = <uv.uv_req_t*> PyMem_Malloc(
264+
sizeof(uv.uv_getaddrinfo_t))
265+
if self.request is NULL:
266+
self.on_done()
267+
raise MemoryError()
268+
265269
self.callback = callback
266270
self.request.data = <void*>self
267271

@@ -279,11 +283,15 @@ cdef class AddrInfoRequest(UVRequest):
279283

280284
cdef class NameInfoRequest(UVRequest):
281285
cdef:
282-
uv.uv_getnameinfo_t _req_data
283286
object callback
284287

285288
def __cinit__(self, Loop loop, callback):
286-
self.request = <uv.uv_req_t*>&self._req_data
289+
self.request = <uv.uv_req_t*> PyMem_Malloc(
290+
sizeof(uv.uv_getnameinfo_t))
291+
if self.request is NULL:
292+
self.on_done()
293+
raise MemoryError()
294+
287295
self.callback = callback
288296
self.request.data = <void*>self
289297

uvloop/handles/async_.pxd

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
cdef class UVAsync(UVHandle):
22
cdef:
3-
uv.uv_async_t _handle_data
43
method_t callback
54
object ctx
65

uvloop/handles/async_.pyx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,12 @@ cdef class UVAsync(UVHandle):
44
cdef int err
55

66
self._start_init(loop)
7-
self._handle = <uv.uv_handle_t*>&self._handle_data
7+
8+
self._handle = <uv.uv_handle_t*> \
9+
PyMem_Malloc(sizeof(uv.uv_async_t))
10+
if self._handle is NULL:
11+
self._abort_init()
12+
raise MemoryError()
813

914
err = uv.uv_async_init(self._loop.uvloop,
1015
<uv.uv_async_t*>self._handle,

uvloop/handles/check.pxd

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
cdef class UVCheck(UVHandle):
22
cdef:
3-
uv.uv_check_t _handle_data
43
Handle h
54
bint running
65

uvloop/handles/check.pyx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,12 @@ cdef class UVCheck(UVHandle):
44
cdef int err
55

66
self._start_init(loop)
7-
self._handle = <uv.uv_handle_t*>&self._handle_data
7+
8+
self._handle = <uv.uv_handle_t*> \
9+
PyMem_Malloc(sizeof(uv.uv_check_t))
10+
if self._handle is NULL:
11+
self._abort_init()
12+
raise MemoryError()
813

914
err = uv.uv_check_init(self._loop.uvloop, <uv.uv_check_t*>self._handle)
1015
if err < 0:

uvloop/handles/handle.pxd

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ cdef class UVHandle:
1717
cdef _error(self, exc, throw)
1818
cdef _fatal_error(self, exc, throw, reason=?)
1919

20+
cdef _free(self)
2021
cdef _close(self)
2122

2223

uvloop/handles/handle.pyx

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,33 +37,47 @@ cdef class UVHandle:
3737
'{} without @no_gc_clear; loop was set to None by GC'
3838
.format(self.__class__.__name__))
3939

40-
if self._handle is NULL or self._closed:
40+
if self._handle is NULL:
4141
return
4242

4343
# -> When we're at this point, something is wrong <-
4444

4545
if self._handle.loop is NULL:
4646
# The handle wasn't initialized with "uv_{handle}_init"
47-
self._handle = NULL
47+
self._closed = 1
48+
self._free()
4849
raise RuntimeError(
4950
'{} is open in __dealloc__ with loop set to NULL'
5051
.format(self.__class__.__name__))
5152

53+
if self._closed == 1:
54+
# So _handle is not NULL and self._closed == 1?
55+
raise RuntimeError(
56+
'{}.__dealloc__: _handle is NULL, _closed == 1'.format(
57+
self.__class__.__name__))
58+
5259
# The handle is dealloced while open. Let's try to close it.
5360
# Situations when this is possible include unhandled exceptions,
5461
# errors during Handle.__cinit__/__init__ etc.
5562
if self._inited:
5663
self._handle.data = <void*> __NOHANDLE__
5764
uv.uv_close(self._handle, __uv_close_handle_cb) # void; no errors
65+
self._handle = NULL
5866
warnings_warn("unclosed resource {!r}".format(self),
5967
ResourceWarning)
68+
else:
69+
# The handle was allocated, but not initialized
70+
self._closed = 1
71+
self._free()
6072

61-
# The handle was allocated, but not initialized
62-
self._closed = 1
73+
74+
cdef _free(self):
75+
PyMem_Free(self._handle)
6376
self._handle = NULL
6477

6578
cdef inline _abort_init(self):
66-
self._handle = NULL
79+
if self._handle is not NULL:
80+
self._free()
6781

6882
IF DEBUG:
6983
name = self.__class__.__name__
@@ -278,19 +292,29 @@ cdef inline bint __ensure_handle_data(uv.uv_handle_t* handle,
278292
cdef void __uv_close_handle_cb(uv.uv_handle_t* handle) with gil:
279293
cdef:
280294
UVHandle h
295+
Loop loop
281296

282297
if handle.data is NULL:
283298
# Shouldn't happen.
284-
raise RuntimeError('uv_handle_t.data is NULL in close callback')
299+
loop = <Loop>handle.loop.data
300+
loop.call_exception_handler({
301+
'message': 'uv_handle_t.data is NULL in close callback'
302+
})
303+
PyMem_Free(handle)
304+
return
285305

286306
if <object>handle.data is not __NOHANDLE__:
287307
h = <UVHandle>handle.data
308+
h._handle = NULL
288309
IF DEBUG:
289310
h._loop._debug_handles_closed.update([
290311
h.__class__.__name__])
312+
h._free()
291313
Py_DECREF(h) # Was INCREFed in UVHandle._close
292314
return
293315

316+
PyMem_Free(handle)
317+
294318

295319
cdef void __close_all_handles(Loop loop):
296320
uv.uv_walk(loop.uvloop, __uv_walk_close_all_handles_cb, <void*>loop) # void

uvloop/handles/idle.pxd

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
cdef class UVIdle(UVHandle):
22
cdef:
3-
uv.uv_idle_t _handle_data
43
Handle h
54
bint running
65

uvloop/handles/idle.pyx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,12 @@ cdef class UVIdle(UVHandle):
44
cdef int err
55

66
self._start_init(loop)
7-
self._handle = <uv.uv_handle_t*>&self._handle_data
7+
8+
self._handle = <uv.uv_handle_t*> \
9+
PyMem_Malloc(sizeof(uv.uv_idle_t))
10+
if self._handle is NULL:
11+
self._abort_init()
12+
raise MemoryError()
813

914
err = uv.uv_idle_init(self._loop.uvloop, <uv.uv_idle_t*>self._handle)
1015
if err < 0:

uvloop/handles/pipe.pxd

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
cdef class UnixServer(UVStreamServer):
22

3-
cdef:
4-
uv.uv_pipe_t _handle_data
5-
63
cdef bind(self, str path)
74
cdef open(self, int sockfd)
85

@@ -13,9 +10,6 @@ cdef class UnixServer(UVStreamServer):
1310

1411
cdef class UnixTransport(UVStream):
1512

16-
cdef:
17-
uv.uv_pipe_t _handle_data
18-
1913
@staticmethod
2014
cdef UnixTransport new(Loop loop, object protocol, Server server,
2115
object waiter)
@@ -26,9 +20,6 @@ cdef class UnixTransport(UVStream):
2620

2721
cdef class ReadUnixTransport(UVStream):
2822

29-
cdef:
30-
uv.uv_pipe_t _handle_data
31-
3223
@staticmethod
3324
cdef ReadUnixTransport new(Loop loop, object protocol, Server server,
3425
object waiter)
@@ -38,9 +29,6 @@ cdef class ReadUnixTransport(UVStream):
3829

3930
cdef class WriteUnixTransport(UVStream):
4031

41-
cdef:
42-
uv.uv_pipe_t _handle_data
43-
4432
@staticmethod
4533
cdef WriteUnixTransport new(Loop loop, object protocol, Server server,
4634
object waiter)

0 commit comments

Comments
 (0)