Commit 4bd8b927 authored by Diego Fronza's avatar Diego Fronza
Browse files

Update locking code based on origin/main

Pulled most recent updates on unix/socket.c from origin/main, it seems
this issue was already handled by those updates.
parent fea4d53c
......@@ -875,19 +875,18 @@ wakeup_socket(isc__socketthread_t *thread, int fd, int msg) {
INSIST(fd >= 0 && fd < (int)thread->manager->maxsocks);
if (msg == SELECT_POKE_CLOSE) {
/* No one should be updating fdstate, so no need to lock it */
LOCK(&thread->fdlock[lockid]);
INSIST(thread->fdstate[fd] == CLOSE_PENDING);
thread->fdstate[fd] = CLOSED;
(void)unwatch_fd(thread, fd, SELECT_POKE_READ);
(void)unwatch_fd(thread, fd, SELECT_POKE_WRITE);
(void)close(fd);
UNLOCK(&thread->fdlock[lockid]);
return;
}
LOCK(&thread->fdlock[lockid]);
if (thread->fdstate[fd] == CLOSE_PENDING) {
UNLOCK(&thread->fdlock[lockid]);
/*
* We accept (and ignore) any error from unwatch_fd() as we are
* closing the socket, hoping it doesn't leave dangling state in
......@@ -898,6 +897,7 @@ wakeup_socket(isc__socketthread_t *thread, int fd, int msg) {
*/
(void)unwatch_fd(thread, fd, SELECT_POKE_READ);
(void)unwatch_fd(thread, fd, SELECT_POKE_WRITE);
UNLOCK(&thread->fdlock[lockid]);
return;
}
if (thread->fdstate[fd] != MANAGED) {
......@@ -1781,11 +1781,13 @@ socketclose(isc__socketthread_t *thread, isc__socket_t *sock, int fd) {
select_poke(thread->manager, thread->threadid, fd, SELECT_POKE_CLOSE);
inc_stats(thread->manager->stats, sock->statsindex[STATID_CLOSE]);
LOCK(&thread->fdlock[lockid]);
if (sock->active == 1) {
dec_stats(thread->manager->stats,
sock->statsindex[STATID_ACTIVE]);
sock->active = 0;
}
UNLOCK(&thread->fdlock[lockid]);
/*
* update manager->maxfd here (XXX: this should be implemented more
......@@ -1826,6 +1828,9 @@ destroy(isc__socket_t **sockp) {
socket_log(sock, NULL, CREATION, "destroying");
isc_refcount_destroy(&sock->references);
LOCK(&sock->lock);
INSIST(ISC_LIST_EMPTY(sock->connect_list));
INSIST(ISC_LIST_EMPTY(sock->accept_list));
INSIST(ISC_LIST_EMPTY(sock->recv_list));
......@@ -1837,6 +1842,10 @@ destroy(isc__socket_t **sockp) {
thread = &manager->threads[sock->threadid];
sock->fd = -1;
sock->threadid = -1;
}
UNLOCK(&sock->lock);
if (fd > 0) {
socketclose(thread, sock, fd);
}
......@@ -1914,15 +1923,18 @@ allocate_socket(isc__socketmgr_t *manager, isc_sockettype_t type,
static void
free_socket(isc__socket_t **socketp) {
isc__socket_t *sock = *socketp;
*socketp = NULL;
INSIST(VALID_SOCKET(sock));
INSIST(isc_refcount_current(&sock->references) == 0);
isc_refcount_destroy(&sock->references);
LOCK(&sock->lock);
INSIST(!sock->connecting);
INSIST(ISC_LIST_EMPTY(sock->recv_list));
INSIST(ISC_LIST_EMPTY(sock->send_list));
INSIST(ISC_LIST_EMPTY(sock->accept_list));
INSIST(ISC_LIST_EMPTY(sock->connect_list));
INSIST(!ISC_LINK_LINKED(sock, link));
UNLOCK(&sock->lock);
sock->common.magic = 0;
sock->common.impmagic = 0;
......@@ -1930,8 +1942,6 @@ free_socket(isc__socket_t **socketp) {
isc_mutex_destroy(&sock->lock);
isc_mem_put(sock->manager->mctx, sock, sizeof(*sock));
*socketp = NULL;
}
#ifdef SO_RCVBUF
......@@ -2813,13 +2823,8 @@ internal_accept(isc__socket_t *sock) {
const char *err = "accept";
INSIST(VALID_SOCKET(sock));
REQUIRE(sock->fd >= 0);
LOCK(&sock->lock);
if (sock->fd < 0) {
/* Socket is gone */
UNLOCK(&sock->lock);
return;
}
socket_log(sock, NULL, TRACE,
"internal_accept called, locked socket");
......@@ -2956,8 +2961,6 @@ internal_accept(isc__socket_t *sock) {
unwatch_fd(thread, sock->fd,
SELECT_POKE_ACCEPT);
UNLOCK(&sock->lock);
if (fd != -1) {
result = make_nonblock(fd);
if (result != ISC_R_SUCCESS) {
......@@ -2966,6 +2969,12 @@ internal_accept(isc__socket_t *sock) {
}
}
/*
* We need to unlock sock->lock now to be able to lock manager->lock
* without risking a deadlock with xmlstats.
*/
UNLOCK(&sock->lock);
/*
* -1 means the new socket didn't happen.
*/
......@@ -3037,7 +3046,7 @@ internal_accept(isc__socket_t *sock) {
inc_stats(manager->stats, sock->statsindex[STATID_ACCEPT]);
} else {
inc_stats(manager->stats, sock->statsindex[STATID_ACCEPTFAIL]);
isc_refcount_decrement(&NEWCONNSOCK(dev)->references);
(void)isc_refcount_decrement(&NEWCONNSOCK(dev)->references);
free_socket((isc__socket_t **)&dev->newsocket);
}
......@@ -3064,13 +3073,8 @@ internal_recv(isc__socket_t *sock) {
isc_socketevent_t *dev;
INSIST(VALID_SOCKET(sock));
REQUIRE(sock->fd >= 0);
LOCK(&sock->lock);
if (sock->fd < 0) {
/* Socket is gone */
UNLOCK(&sock->lock);
return;
}
dev = ISC_LIST_HEAD(sock->recv_list);
if (dev == NULL) {
goto finish;
......@@ -3123,13 +3127,8 @@ internal_send(isc__socket_t *sock) {
isc_socketevent_t *dev;
INSIST(VALID_SOCKET(sock));
REQUIRE(sock->fd >= 0);
LOCK(&sock->lock);
if (sock->fd < 0) {
/* Socket is gone */
UNLOCK(&sock->lock);
return;
}
dev = ISC_LIST_HEAD(sock->send_list);
if (dev == NULL) {
goto finish;
......@@ -3193,15 +3192,22 @@ process_fd(isc__socketthread_t *thread, int fd, bool readable,
return;
}
if (isc_refcount_increment(&sock->references) == 0) {
LOCK(&sock->lock);
if (sock->fd < 0) {
/*
* Sock is being closed, it will be destroyed, bail.
* Sock is being closed - the final external reference
* is gone but it was not yet removed from event loop
* and fdstate[]/fds[] as destroy() is waiting on
* thread->fdlock[lockid] or sock->lock that we're holding.
* Just release the locks and bail.
*/
(void)isc_refcount_decrement(&sock->references);
UNLOCK(&sock->lock);
UNLOCK(&thread->fdlock[lockid]);
return;
}
REQUIRE(readable || writeable);
if (readable) {
if (sock->listener) {
internal_accept(sock);
......@@ -3219,9 +3225,6 @@ process_fd(isc__socketthread_t *thread, int fd, bool readable,
}
UNLOCK(&thread->fdlock[lockid]);
if (isc_refcount_decrement(&sock->references) == 1) {
destroy(&sock);
}
}
/*
......@@ -4189,6 +4192,10 @@ socket_send(isc__socket_t *sock, isc_socketevent_t *dev, isc_task_t *task,
case DOIO_HARD:
case DOIO_SUCCESS:
if (!have_lock) {
LOCK(&sock->lock);
have_lock = true;
}
if ((flags & ISC_SOCKFLAG_IMMEDIATE) == 0) {
send_senddone_event(sock, &dev);
}
......@@ -4928,8 +4935,7 @@ internal_connect(isc__socket_t *sock) {
char peerbuf[ISC_SOCKADDR_FORMATSIZE];
INSIST(VALID_SOCKET(sock));
LOCK(&sock->lock);
REQUIRE(sock->fd >= 0);
/*
* Get the first item off the connect list.
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment