-
-
Notifications
You must be signed in to change notification settings - Fork 31.7k
socket destructor: implement finalizer #70777
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
The PEP-442 helped to make object finalization safer, but it's just an API, it's not widely used in the Python core yet. io.FileIO has a nice implementation, but socket.socket and os.scandir don't. I noticed this while working on the issue bpo-26567 which indirectly resurected a destroyed socket (in test_socket). As I workaround, I reverted my change on socket destructor, but I'm interested to enhance socket destructor to be able to use the new tracemalloc feature of the warnings module. |
Attached patch adds a finalizer to _socket.socket() and use PyErr_ResourceWarning() to log the traceback where the socket was created in the warning logger (if tracemalloc is enabled, see issue bpo-26567). |
It's unclear to me if it's needed to call the following code in sock_dealloc(): + if (PyObject_CallFinalizerFromDealloc((PyObject *)s) < 0) It looks like this code is not needed, since sock_finalize() is called before sock_dealloc(). |
sock_finalize() is only called explicitly if there is a reference cycle. This is why sock_dealloc() has to call it. |
2016-03-19 11:05 GMT+01:00 Antoine Pitrou <report@bugs.python.org>:
I'm fine with keeping sock_dealloc() to call sock_finalize(), but I Example: import socket
s=socket.socket()
s=None With this code, sock_finalize() is called before sock_dealloc(): #0 sock_finalize (s=0x7ffff0730c28) at |
Le 19/03/2016 14:07, STINNER Victor a écrit :
Ah, that's probably because socket.socket is a Python subclass. |
Antoine Pitrou added the comment:
Oh, I forgot this sublte implementation detail, _socket.socket base Example with _socket: import _socket
s=_socket.socket()
s=None Ok, in this case sock_finalize() is called by sock_dealloc(). |
Now that there is a safe finalizer, I wonder if it should release the GIL, as in sock_close(). |
Ah yes, good idea. I updated my patch. I also changed the change to begin by setting the sock_fd attribute to -1, before closing the socket (since the GIL is now released, the order matters). |
On the review, Antoine wrote: I disagree. It's a deliberate choice to keep the socket open while logging the ResourceWarning. Example: import socket
import warnings
def show(msg):
s = msg.source
#s.close()
if s.fileno() >= 0:
print("socket open")
else:
print("socket closed")
try:
name = s.getsockname()
except Exception as exc:
name = str(exc)
print("getsockname(): %r" % (name,))
warnings._showwarnmsg = show
s = socket.socket()
s = None Output with sock_finalize-2.patch: If you uncomment the s.close() (or set sock_fd to -1 in the C code): IMHO it's ok to give access to socket methods in the warning logger. |
Oh, I see. Perhaps add a comment then? |
Sure, done. Does it look better now? |
Yes, it looks good to me. |
New changeset 46329eec5515 by Victor Stinner in branch 'default': |
Thanks for the review. I pushed my change. |
New changeset a97d317dec85 by Victor Stinner in branch 'default': |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: