Skip to content

Commit 7e75670

Browse files
committed
cffi: simplify destroying ares channel
Use ffi.gc instead of a dedicated function.
1 parent 53cb9eb commit 7e75670

File tree

2 files changed

+14
-47
lines changed

2 files changed

+14
-47
lines changed

src/pycares/__init__.py

+14-43
Original file line numberDiff line numberDiff line change
@@ -81,14 +81,6 @@ class AresError(Exception):
8181
pass
8282

8383

84-
def check_channel(f):
85-
@functools.wraps(f)
86-
def wrapper(self, *args, **kwds):
87-
if not self.channel:
88-
raise AresError("Channel has already been destroyed")
89-
return f(self, *args, **kwds)
90-
return wrapper
91-
9284
# callback helpers
9385

9486
_global_set = set()
@@ -390,7 +382,7 @@ def __init__(self,
390382
if r != _lib.ARES_SUCCESS:
391383
raise AresError('Failed to initialize c-ares channel')
392384

393-
self.channel = channel[0]
385+
self._channel = _ffi.gc(channel, lambda x: _lib.ares_destroy(x[0]))
394386

395387
if servers:
396388
self._set_servers(servers)
@@ -401,20 +393,9 @@ def __init__(self,
401393
if local_dev:
402394
self.set_local_dev(local_dev)
403395

404-
def __del__(self):
405-
self.destroy()
406-
407-
def destroy(self):
408-
if self.channel:
409-
_lib.ares_destroy(self.channel)
410-
self.channel = None
411-
self._sock_state_cb_handle = None
412-
413-
@check_channel
414396
def cancel(self):
415-
_lib.ares_cancel(self.channel)
397+
_lib.ares_cancel(self._channel[0])
416398

417-
@check_channel
418399
def _set_servers(self, servers):
419400
c = _ffi.new("struct ares_addr_node[%d]" % len(servers))
420401
for i, server in enumerate(servers):
@@ -428,15 +409,14 @@ def _set_servers(self, servers):
428409
if i > 0:
429410
c[i - 1].next = _ffi.addressof(c[i])
430411

431-
r = _lib.ares_set_servers(self.channel, c)
412+
r = _lib.ares_set_servers(self._channel[0], c)
432413
if r != _lib.ARES_SUCCESS:
433414
raise AresError(r, errno.strerror(r))
434415

435-
@check_channel
436416
def _get_servers(self):
437417
servers = _ffi.new("struct ares_addr_node **")
438418

439-
r = _lib.ares_get_servers(self.channel, servers)
419+
r = _lib.ares_get_servers(self._channel[0], servers)
440420
if r != _lib.ARES_SUCCESS:
441421
raise AresError(r, errno.strerror(r))
442422

@@ -457,12 +437,11 @@ def _get_servers(self):
457437

458438
servers = property(_get_servers, _set_servers)
459439

460-
@check_channel
461440
def getsock(self):
462441
rfds = []
463442
wfds = []
464443
socks = _ffi.new("ares_socket_t [%d]" % _lib.ARES_GETSOCK_MAXNUM)
465-
bitmask = _lib.ares_getsock(self.channel, socks, _lib.ARES_GETSOCK_MAXNUM)
444+
bitmask = _lib.ares_getsock(self._channel[0], socks, _lib.ARES_GETSOCK_MAXNUM)
466445
for i in range(_lib.ARES_GETSOCK_MAXNUM):
467446
if _lib.ARES_GETSOCK_READABLE(bitmask, i):
468447
rfds.append(socks[i])
@@ -471,12 +450,9 @@ def getsock(self):
471450

472451
return rfds, wfds
473452

474-
475-
@check_channel
476453
def process_fd(self, read_fd, write_fd):
477-
_lib.ares_process_fd(self.channel, _ffi.cast("ares_socket_t", read_fd), _ffi.cast("ares_socket_t", write_fd))
454+
_lib.ares_process_fd(self._channel[0], _ffi.cast("ares_socket_t", read_fd), _ffi.cast("ares_socket_t", write_fd))
478455

479-
@check_channel
480456
def timeout(self, t = None):
481457
maxtv = _ffi.NULL
482458
tv = _ffi.new("struct timeval*")
@@ -489,14 +465,13 @@ def timeout(self, t = None):
489465
else:
490466
raise ValueError("timeout needs to be a positive number or None")
491467

492-
_lib.ares_timeout(self.channel, maxtv, tv)
468+
_lib.ares_timeout(self._channel[0], maxtv, tv)
493469

494470
if tv == _ffi.NULL:
495471
return 0.0
496472

497473
return (tv.tv_sec + tv.tv_usec / 1000000.0)
498474

499-
@check_channel
500475
def gethostbyaddr(self, addr, callback):
501476
if not callable(callback):
502477
raise TypeError("a callable is required")
@@ -514,16 +489,15 @@ def gethostbyaddr(self, addr, callback):
514489

515490
userdata = _ffi.new_handle(callback)
516491
_global_set.add(userdata)
517-
_lib.ares_gethostbyaddr(self.channel, address, _ffi.sizeof(address[0]), family, _host_cb, userdata)
492+
_lib.ares_gethostbyaddr(self._channel[0], address, _ffi.sizeof(address[0]), family, _host_cb, userdata)
518493

519-
@check_channel
520494
def gethostbyname(self, name, family, callback):
521495
if not callable(callback):
522496
raise TypeError("a callable is required")
523497

524498
userdata = _ffi.new_handle(callback)
525499
_global_set.add(userdata)
526-
_lib.ares_gethostbyname(self.channel, parse_name(name), family, _host_cb, userdata)
500+
_lib.ares_gethostbyname(self._channel[0], parse_name(name), family, _host_cb, userdata)
527501

528502
def query(self, name, query_type, callback):
529503
if not callable(callback):
@@ -534,20 +508,18 @@ def query(self, name, query_type, callback):
534508

535509
userdata = _ffi.new_handle((callback, query_type))
536510
_global_set.add(userdata)
537-
_lib.ares_query(self.channel, parse_name(name), _lib.C_IN, query_type, _query_cb, userdata)
511+
_lib.ares_query(self._channel[0], parse_name(name), _lib.C_IN, query_type, _query_cb, userdata)
538512

539-
@check_channel
540513
def set_local_ip(self, ip):
541514
addr4 = _ffi.new("struct in_addr*")
542515
addr6 = _ffi.new("struct ares_in6_addr*")
543516
if _lib.ares_inet_pton(socket.AF_INET, ascii_bytes(ip), addr4) == 1:
544-
_lib.ares_set_local_ip4(self.channel, socket.ntohl(addr4.s_addr))
517+
_lib.ares_set_local_ip4(self._channel[0], socket.ntohl(addr4.s_addr))
545518
elif _lib.ares_inet_pton(socket.AF_INET6, ascii_bytes(ip), addr6) == 1:
546-
_lib.ares_set_local_ip6(self.channel, addr6)
519+
_lib.ares_set_local_ip6(self._channel[0], addr6)
547520
else:
548521
raise ValueError("invalid IP address")
549522

550-
@check_channel
551523
def getnameinfo(self, ip_port, flags, callback):
552524
if not callable(callback):
553525
raise TypeError("a callable is required")
@@ -573,11 +545,10 @@ def getnameinfo(self, ip_port, flags, callback):
573545

574546
userdata = _ffi.new_handle(callback)
575547
_global_set.add(userdata)
576-
_lib.ares_getnameinfo(self.channel, _ffi.cast("struct sockaddr*", sa), _ffi.sizeof(sa[0]), flags, _nameinfo_cb, userdata)
548+
_lib.ares_getnameinfo(self._channel[0], _ffi.cast("struct sockaddr*", sa), _ffi.sizeof(sa[0]), flags, _nameinfo_cb, userdata)
577549

578-
@check_channel
579550
def set_local_dev(self, dev):
580-
_lib.ares_set_local_dev(self.channel, dev)
551+
_lib.ares_set_local_dev(self._channel[0], dev)
581552

582553

583554
class AresResult:

tests/tests.py

-4
Original file line numberDiff line numberDiff line change
@@ -310,10 +310,6 @@ def cb(result, errorno):
310310
self.assertEqual(self.result, None)
311311
self.assertEqual(self.errorno, pycares.errno.ARES_ECANCELLED)
312312

313-
def test_channel_destroyed(self):
314-
self.channel.destroy()
315-
self.assertRaises(pycares.AresError, self.channel.gethostbyname, 'google.com', socket.AF_INET, lambda *x: None)
316-
317313
def test_query_bad_type(self):
318314
self.assertRaises(ValueError, self.channel.query, 'google.com', 667, lambda *x: None)
319315
self.wait()

0 commit comments

Comments
 (0)