1
0
mirror of git://sourceware.org/git/lvm2.git synced 2024-12-22 17:35:59 +03:00

Fix a double close in clvmd.

The management threads (main_loop, the socket thread) could close a single fd
twice in a row sometimes. At least one other thread can be running at the same
time as the threads doing the double close. That one running thread also
happens to do some IO (namely, open /proc/devices, read from it, close it). If
there was enough "demand" for the local socket, this could happen:

- a connection to clvmd is about to finish, let's say the fd is 13 (it often
  happens to be in my test script, don't ask why)
- the local_sock thread calls close(13)
- the lvm thread calls open("/proc/devices"...) and gets 13
- the main_loop thread calls close(13) [OOPS!]
- new connection arrives, and is accept'd by a (new) local_sock thread
- the accept gives an fd of 13 (since it's the lowest free fd at this point)
- the lvm thread gets around to read from it's /proc/devices handle... 13,
  again
- the lvm thread hangs forever trying to read from the socket instead of
  /proc/devices

Signed-off-by: Petr Rockai <prockai@redhat.com>
Reviewed-by: Milan Broz <mbroz@redhat.com>
This commit is contained in:
Petr Rockai 2010-10-27 09:13:37 +00:00
parent 07d7f642f8
commit 9b2800e861

View File

@ -838,7 +838,10 @@ static void main_loop(int local_sock, int cmd_timeout)
lastfd->next = thisfd->next; lastfd->next = thisfd->next;
free_fd = thisfd; free_fd = thisfd;
thisfd = lastfd; thisfd = lastfd;
close(free_fd->fd); if (free_fd->fd >= 0) {
close(free_fd->fd);
free_fd->fd = -1;
}
/* Queue cleanup, this also frees the client struct */ /* Queue cleanup, this also frees the client struct */
add_to_lvmqueue(free_fd, NULL, 0, NULL); add_to_lvmqueue(free_fd, NULL, 0, NULL);
@ -1088,7 +1091,10 @@ static int read_from_local_sock(struct local_client *thisfd)
thisfd->bits.localsock.pipe_client->bits.pipe.client = thisfd->bits.localsock.pipe_client->bits.pipe.client =
NULL; NULL;
close(thisfd->fd); if (thisfd->fd >= 0) {
close(thisfd->fd);
thisfd->fd = -1;
}
return 0; return 0;
} else { } else {
int comms_pipe[2]; int comms_pipe[2];