Skip to content

Commit

Permalink
asyn-thread: issue CURL_POLL_REMOVE before closing socket
Browse files Browse the repository at this point in the history
This avoids EBADF errors from EPOLL_CTL_DEL operations in the
ephiperfifo.c example.  EBADF is dangerous in multi-threaded
applications where I rely on epoll_ctl to operate on the same
epoll description from different threads.

Follow-up to eb9a604

Bug: https://curl.haxx.se/mail/lib-2019-08/0026.html
Closes #4211
  • Loading branch information
Eric Wong authored and bagder committed Aug 11, 2019
1 parent 4a962ff commit 17d1e27
Showing 1 changed file with 20 additions and 5 deletions.
25 changes: 20 additions & 5 deletions lib/asyn-thread.c
Expand Up @@ -164,6 +164,7 @@ struct thread_sync_data {
duplicate */ duplicate */
int port; int port;
#ifdef HAVE_SOCKETPAIR #ifdef HAVE_SOCKETPAIR
struct connectdata *conn;
curl_socket_t sock_pair[2]; /* socket pair */ curl_socket_t sock_pair[2]; /* socket pair */
#endif #endif
int sock_error; int sock_error;
Expand Down Expand Up @@ -201,11 +202,10 @@ void destroy_thread_sync_data(struct thread_sync_data * tsd)
Curl_freeaddrinfo(tsd->res); Curl_freeaddrinfo(tsd->res);


#ifdef HAVE_SOCKETPAIR #ifdef HAVE_SOCKETPAIR
/* close socket pair */ /*
if(tsd->sock_pair[0] != CURL_SOCKET_BAD) { * close one end of the socket pair (may be done in resolver thread);
sclose(tsd->sock_pair[0]); * the other end (for reading) is always closed in the parent thread.
} */

if(tsd->sock_pair[1] != CURL_SOCKET_BAD) { if(tsd->sock_pair[1] != CURL_SOCKET_BAD) {
sclose(tsd->sock_pair[1]); sclose(tsd->sock_pair[1]);
} }
Expand Down Expand Up @@ -382,6 +382,10 @@ static void destroy_async_data(struct Curl_async *async)
if(async->os_specific) { if(async->os_specific) {
struct thread_data *td = (struct thread_data*) async->os_specific; struct thread_data *td = (struct thread_data*) async->os_specific;
int done; int done;
#ifdef HAVE_SOCKETPAIR
curl_socket_t sock_rd = td->tsd.sock_pair[0];
struct connectdata *conn = td->tsd.conn;
#endif


/* /*
* if the thread is still blocking in the resolve syscall, detach it and * if the thread is still blocking in the resolve syscall, detach it and
Expand All @@ -403,6 +407,15 @@ static void destroy_async_data(struct Curl_async *async)


free(async->os_specific); free(async->os_specific);
} }
#ifdef HAVE_SOCKETPAIR
/*
* ensure CURLMOPT_SOCKETFUNCTION fires CURL_POLL_REMOVE
* before the FD is invalidated to avoid EBADF on EPOLL_CTL_DEL
*/
if(conn)
Curl_multi_closed(conn->data, sock_rd);
sclose(sock_rd);
#endif
} }
async->os_specific = NULL; async->os_specific = NULL;


Expand Down Expand Up @@ -644,6 +657,8 @@ int Curl_resolver_getsock(struct connectdata *conn,
if(td) { if(td) {
/* return read fd to client for polling the DNS resolution status */ /* return read fd to client for polling the DNS resolution status */
socks[0] = td->tsd.sock_pair[0]; socks[0] = td->tsd.sock_pair[0];
DEBUGASSERT(td->tsd.conn == conn || !td->tsd.conn);
td->tsd.conn = conn;
ret_val = GETSOCK_READSOCK(0); ret_val = GETSOCK_READSOCK(0);
} }
else { else {
Expand Down

0 comments on commit 17d1e27

Please sign in to comment.