make _socket.socket weakrefable (closes #22569)

Patch from Alex Gaynor.
diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c
index 0127a6c..e9e4479 100644
--- a/Modules/socketmodule.c
+++ b/Modules/socketmodule.c
@@ -3115,6 +3115,8 @@
 {
     if (s->sock_fd != -1)
         (void) SOCKETCLOSE(s->sock_fd);
+    if (s->weakreflist != NULL)
+        PyObject_ClearWeakRefs((PyObject *)s);
     Py_TYPE(s)->tp_free((PyObject *)s);
 }
 
@@ -3163,6 +3165,7 @@
         ((PySocketSockObject *)new)->sock_fd = -1;
         ((PySocketSockObject *)new)->sock_timeout = -1.0;
         ((PySocketSockObject *)new)->errorhandler = &set_error;
+        ((PySocketSockObject *)new)->weakreflist = NULL;
     }
     return new;
 }
@@ -3226,7 +3229,7 @@
     0,                                          /* tp_traverse */
     0,                                          /* tp_clear */
     0,                                          /* tp_richcompare */
-    0,                                          /* tp_weaklistoffset */
+    offsetof(PySocketSockObject, weakreflist),  /* tp_weaklistoffset */
     0,                                          /* tp_iter */
     0,                                          /* tp_iternext */
     sock_methods,                               /* tp_methods */
diff --git a/Modules/socketmodule.h b/Modules/socketmodule.h
index 8515499..d98e00e 100644
--- a/Modules/socketmodule.h
+++ b/Modules/socketmodule.h
@@ -132,6 +132,7 @@
                                         sets a Python exception */
     double sock_timeout;                 /* Operation timeout in seconds;
                                         0.0 means non-blocking */
+    PyObject *weakreflist;
 } PySocketSockObject;
 
 /* --- C API ----------------------------------------------------*/