Fix "maximum recursion depth exceeded in GreenSocket.__del__"

Closes #137
Closes #148
This commit is contained in:
Jakub Stasiak
2014-10-16 00:01:29 +01:00
parent 0b8f44f244
commit 325b5afd1f
2 changed files with 28 additions and 2 deletions

View File

@@ -119,6 +119,9 @@ class GreenSocket(object):
to save syscalls.
"""
# This placeholder is to prevent __getattr__ from creating an infinite call loop
fd = None
def __init__(self, family_or_realsock=socket.AF_INET, *args, **kwargs):
should_set_nonblocking = kwargs.pop('set_nonblocking', True)
if isinstance(family_or_realsock, six.integer_types):
@@ -175,6 +178,8 @@ class GreenSocket(object):
# If we find such attributes - only attributes having __get__ might be cached.
# For now - I do not want to complicate it.
def __getattr__(self, name):
if self.fd is None:
raise AttributeError(name)
attr = getattr(self.fd, name)
setattr(self, name, attr)
return attr
@@ -216,7 +221,10 @@ class GreenSocket(object):
self._closed = True
def __del__(self):
self.close()
# This is in case self.close is not assigned yet (currently the constructor does it)
close = getattr(self, 'close', None)
if close is not None:
close()
def connect(self, address):
if self.act_non_blocking:

View File

@@ -9,10 +9,12 @@ import socket as _orig_sock
import sys
import tempfile
from nose.tools import eq_
from eventlet import event, greenio, debug
from eventlet.hubs import get_hub
from eventlet.green import select, socket, time, ssl
from eventlet.support import get_errno, six
from eventlet.support import capture_stderr, get_errno, six
from tests import (
LimitedTestCase, main,
skip_with_pyevent, skipped, skip_if, skip_on_windows,
@@ -895,5 +897,21 @@ def test_set_nonblocking():
assert new_flags == (orig_flags | os.O_NONBLOCK)
def test_socket_del_fails_gracefully_when_not_fully_initialized():
# Regression introduced in da87716714689894f23d0db7b003f26d97031e83, reported in:
# * GH #137 https://github.com/eventlet/eventlet/issues/137
# * https://bugs.launchpad.net/oslo.messaging/+bug/1369999
class SocketSubclass(socket.socket):
def __init__(self):
pass
with capture_stderr() as err:
SocketSubclass()
assert err.getvalue() == ''
if __name__ == '__main__':
main()