@@ -169,26 +169,30 @@ static void *nogvl_connect(void *ptr) {
169
169
170
170
#ifndef _WIN32
171
171
/*
172
- * Redirect clientfd to a dummy socket for mysql_close to
173
- * write, shutdown, and close on as a no-op.
174
- * We do this hack because we want to call mysql_close to release
175
- * memory, but do not want mysql_close to drop connections in the
176
- * parent if the socket got shared in fork.
172
+ * Redirect clientfd to /dev/null for mysql_close and SSL_close to write,
173
+ * shutdown, and close. The hack is needed to prevent shutdown() from breaking
174
+ * a socket that may be in use by the parent or other processes after fork.
175
+ *
176
+ * /dev/null is used to absorb writes; previously a dummy socket was used, but
177
+ * it could not abosrb writes and caused openssl to go into an infinite loop.
178
+ *
177
179
* Returns Qtrue or Qfalse (success or failure)
180
+ *
181
+ * Note: if this function is needed on Windows, use "nul" instead of "/dev/null"
178
182
*/
179
183
static VALUE invalidate_fd (int clientfd )
180
184
{
181
185
#ifdef SOCK_CLOEXEC
182
186
/* Atomically set CLOEXEC on the new FD in case another thread forks */
183
- int sockfd = socket ( AF_UNIX , SOCK_STREAM | SOCK_CLOEXEC , 0 );
187
+ int sockfd = open ( "/dev/null" , O_RDWR | O_CLOEXEC );
184
188
if (sockfd < 0 ) {
185
189
/* Maybe SOCK_CLOEXEC is defined but not available on this kernel */
186
- int sockfd = socket ( AF_UNIX , SOCK_STREAM , 0 );
190
+ int sockfd = open ( "/dev/null" , O_RDWR );
187
191
fcntl (sockfd , F_SETFD , FD_CLOEXEC );
188
192
}
189
193
#else
190
194
/* Well we don't have SOCK_CLOEXEC, so just set FD_CLOEXEC quickly */
191
- int sockfd = socket ( AF_UNIX , SOCK_STREAM , 0 );
195
+ int sockfd = open ( "/dev/null" , O_RDWR );
192
196
fcntl (sockfd , F_SETFD , FD_CLOEXEC );
193
197
#endif
194
198
0 commit comments