Skip to content

Commit 0de437d

Browse files
authored
bpo-25920: Remove socket.getaddrinfo() lock on macOS (GH-20177)
On macOS, socket.getaddrinfo() no longer uses an internal lock to prevent race conditions when calling getaddrinfo(). getaddrinfo is thread-safe is macOS 10.5, whereas Python 3.9 requires macOS 10.6 or newer. The lock was also used on FreeBSD older than 5.3, OpenBSD older than 201311 and NetBSD older than 4.
1 parent 7536432 commit 0de437d

File tree

2 files changed

+9
-47
lines changed

2 files changed

+9
-47
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
On macOS, when building Python for macOS 10.4 and older, which wasn't the case
2+
for python.org macOS installer, :func:`socket.getaddrinfo` no longer uses an
3+
internal lock to prevent race conditions when calling ``getaddrinfo()`` which
4+
is thread-safe since macOS 10.5. Python 3.9 requires macOS 10.6 or newer. The
5+
internal lock caused random hang on fork when another thread was calling
6+
:func:`socket.getaddrinfo`. The lock was also used on FreeBSD older than 5.3,
7+
OpenBSD older than 201311 and NetBSD older than 4.

Diff for: Modules/socketmodule.c

+2-47
Original file line numberDiff line numberDiff line change
@@ -197,43 +197,6 @@ if_indextoname(index) -- return the corresponding interface name\n\
197197
# define USE_GETHOSTBYNAME_LOCK
198198
#endif
199199

200-
/* To use __FreeBSD_version, __OpenBSD__, and __NetBSD_Version__ */
201-
#ifdef HAVE_SYS_PARAM_H
202-
#include <sys/param.h>
203-
#endif
204-
/* On systems on which getaddrinfo() is believed to not be thread-safe,
205-
(this includes the getaddrinfo emulation) protect access with a lock.
206-
207-
getaddrinfo is thread-safe on Mac OS X 10.5 and later. Originally it was
208-
a mix of code including an unsafe implementation from an old BSD's
209-
libresolv. In 10.5 Apple reimplemented it as a safe IPC call to the
210-
mDNSResponder process. 10.5 is the first be UNIX '03 certified, which
211-
includes the requirement that getaddrinfo be thread-safe. See issue #25924.
212-
213-
It's thread-safe in OpenBSD starting with 5.4, released Nov 2013:
214-
http://www.openbsd.org/plus54.html
215-
216-
It's thread-safe in NetBSD starting with 4.0, released Dec 2007:
217-
218-
http://cvsweb.netbsd.org/bsdweb.cgi/src/lib/libc/net/getaddrinfo.c.diff?r1=1.82&r2=1.83
219-
*/
220-
#if ((defined(__APPLE__) && \
221-
MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5) || \
222-
(defined(__FreeBSD__) && __FreeBSD_version+0 < 503000) || \
223-
(defined(__OpenBSD__) && OpenBSD+0 < 201311) || \
224-
(defined(__NetBSD__) && __NetBSD_Version__+0 < 400000000) || \
225-
!defined(HAVE_GETADDRINFO))
226-
#define USE_GETADDRINFO_LOCK
227-
#endif
228-
229-
#ifdef USE_GETADDRINFO_LOCK
230-
#define ACQUIRE_GETADDRINFO_LOCK PyThread_acquire_lock(netdb_lock, 1);
231-
#define RELEASE_GETADDRINFO_LOCK PyThread_release_lock(netdb_lock);
232-
#else
233-
#define ACQUIRE_GETADDRINFO_LOCK
234-
#define RELEASE_GETADDRINFO_LOCK
235-
#endif
236-
237200
#if defined(__APPLE__) || defined(__CYGWIN__) || defined(__NetBSD__)
238201
# include <sys/ioctl.h>
239202
#endif
@@ -1061,7 +1024,7 @@ new_sockobject(SOCKET_T fd, int family, int type, int proto)
10611024

10621025
/* Lock to allow python interpreter to continue, but only allow one
10631026
thread to be in gethostbyname or getaddrinfo */
1064-
#if defined(USE_GETHOSTBYNAME_LOCK) || defined(USE_GETADDRINFO_LOCK)
1027+
#if defined(USE_GETHOSTBYNAME_LOCK)
10651028
static PyThread_type_lock netdb_lock;
10661029
#endif
10671030

@@ -1086,14 +1049,12 @@ setipaddr(const char *name, struct sockaddr *addr_ret, size_t addr_ret_size, int
10861049
hints.ai_socktype = SOCK_DGRAM; /*dummy*/
10871050
hints.ai_flags = AI_PASSIVE;
10881051
Py_BEGIN_ALLOW_THREADS
1089-
ACQUIRE_GETADDRINFO_LOCK
10901052
error = getaddrinfo(NULL, "0", &hints, &res);
10911053
Py_END_ALLOW_THREADS
10921054
/* We assume that those thread-unsafe getaddrinfo() versions
10931055
*are* safe regarding their return value, ie. that a
10941056
subsequent call to getaddrinfo() does not destroy the
10951057
outcome of the first call. */
1096-
RELEASE_GETADDRINFO_LOCK
10971058
if (error) {
10981059
set_gaierror(error);
10991060
return -1;
@@ -1194,7 +1155,6 @@ setipaddr(const char *name, struct sockaddr *addr_ret, size_t addr_ret_size, int
11941155
memset(&hints, 0, sizeof(hints));
11951156
hints.ai_family = af;
11961157
Py_BEGIN_ALLOW_THREADS
1197-
ACQUIRE_GETADDRINFO_LOCK
11981158
error = getaddrinfo(name, NULL, &hints, &res);
11991159
#if defined(__digital__) && defined(__unix__)
12001160
if (error == EAI_NONAME && af == AF_UNSPEC) {
@@ -1205,7 +1165,6 @@ setipaddr(const char *name, struct sockaddr *addr_ret, size_t addr_ret_size, int
12051165
}
12061166
#endif
12071167
Py_END_ALLOW_THREADS
1208-
RELEASE_GETADDRINFO_LOCK /* see comment in setipaddr() */
12091168
if (error) {
12101169
set_gaierror(error);
12111170
return -1;
@@ -6563,10 +6522,8 @@ socket_getaddrinfo(PyObject *self, PyObject *args, PyObject* kwargs)
65636522
hints.ai_protocol = protocol;
65646523
hints.ai_flags = flags;
65656524
Py_BEGIN_ALLOW_THREADS
6566-
ACQUIRE_GETADDRINFO_LOCK
65676525
error = getaddrinfo(hptr, pptr, &hints, &res0);
65686526
Py_END_ALLOW_THREADS
6569-
RELEASE_GETADDRINFO_LOCK /* see comment in setipaddr() */
65706527
if (error) {
65716528
set_gaierror(error);
65726529
goto err;
@@ -6659,10 +6616,8 @@ socket_getnameinfo(PyObject *self, PyObject *args)
66596616
hints.ai_socktype = SOCK_DGRAM; /* make numeric port happy */
66606617
hints.ai_flags = AI_NUMERICHOST; /* don't do any name resolution */
66616618
Py_BEGIN_ALLOW_THREADS
6662-
ACQUIRE_GETADDRINFO_LOCK
66636619
error = getaddrinfo(hostp, pbuf, &hints, &res);
66646620
Py_END_ALLOW_THREADS
6665-
RELEASE_GETADDRINFO_LOCK /* see comment in setipaddr() */
66666621
if (error) {
66676622
set_gaierror(error);
66686623
goto fail;
@@ -8422,7 +8377,7 @@ PyInit__socket(void)
84228377
#endif /* _MSTCPIP_ */
84238378

84248379
/* Initialize gethostbyname lock */
8425-
#if defined(USE_GETHOSTBYNAME_LOCK) || defined(USE_GETADDRINFO_LOCK)
8380+
#if defined(USE_GETHOSTBYNAME_LOCK)
84268381
netdb_lock = PyThread_allocate_lock();
84278382
#endif
84288383

0 commit comments

Comments
 (0)