Skip to content

Commit 6206d2f

Browse files
committed
Atomically set CLOEXEC on the dummy socket in invalidate_fd if possible
1 parent 90d6626 commit 6206d2f

File tree

1 file changed

+14
-2
lines changed

1 file changed

+14
-2
lines changed

ext/mysql2/client.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <sys/socket.h>
77
#endif
88
#include <unistd.h>
9+
#include <fcntl.h>
910
#include "wait_for_single_fd.h"
1011

1112
#include "mysql_enc_name_to_ruby.h"
@@ -170,12 +171,23 @@ static void *nogvl_connect(void *ptr) {
170171
* We do this hack because we want to call mysql_close to release
171172
* memory, but do not want mysql_close to drop connections in the
172173
* parent if the socket got shared in fork.
173-
* Returns Qtrue or false (success or failure)
174+
* Returns Qtrue or Qfalse (success or failure)
174175
*/
175176
static VALUE invalidate_fd(int clientfd)
176177
{
177-
/* TODO: set cloexec flags, atomically if possible */
178+
#ifdef SOCK_CLOEXEC
179+
/* Atomically set CLOEXEC on the new FD in case another thread forks */
180+
int sockfd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
181+
if (sockfd < 0) {
182+
/* Maybe SOCK_CLOEXEC is defined but not available on this kernel */
183+
int sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
184+
fcntl(sockfd, F_SETFD, FD_CLOEXEC);
185+
}
186+
#else
187+
/* Well we don't have SOCK_CLOEXEC, so just set FD_CLOEXEC quickly */
178188
int sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
189+
fcntl(sockfd, F_SETFD, FD_CLOEXEC);
190+
#endif
179191

180192
if (sockfd < 0) {
181193
/*

0 commit comments

Comments
 (0)