Fix ADB daemon file descriptor leak

The ADB (Android Debug Bridge) daemon suffers from a file descriptor leak.
When transfering file descriptors, opened by the adbd daemon, to a JDWP
process for debugging through sendmsg, the file descriptor is duplicated
by the kernel and a copy is transfered to the JDWP process.
Adbd neglects to close it's copy of the descriptor after the sendmsg call
which causes a file descriptor leak in the process.
Eventually this causes the daemon to hit its maximum roof of opened file
descriptors thus making it impossible for the process to serve any new
commands from the adb server.
Jdwp_service.c has been modified to close the file descriptor after the
send message call has succeded.
Also, the socket used for transfering the file descriptor is set to blocking
mode before the sendmsg call since the adbd processes needs to know when the
duplication has been completed by the kernel.
The flags are reset to its original state after the sendmsg call.

Change-Id: I76b15460301ac01e432f5ce8678ff58c658c16f2
Signed-off-by: Christian Bejram <christian.bejram@stericsson.com>
This commit is contained in:
Teddie Stenvi 2010-02-15 12:20:44 +01:00 committed by Christian Bejram
parent 13b012aaff
commit 8f5daadcc1
1 changed files with 26 additions and 1 deletions

View File

@ -5,6 +5,7 @@
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
/* here's how these things work.
@ -320,6 +321,7 @@ jdwp_process_event( int socket, unsigned events, void* _proc )
struct iovec iov;
char dummy = '!';
char buffer[sizeof(struct cmsghdr) + sizeof(int)];
int flags;
iov.iov_base = &dummy;
iov.iov_len = 1;
@ -337,10 +339,27 @@ jdwp_process_event( int socket, unsigned events, void* _proc )
cmsg->cmsg_type = SCM_RIGHTS;
((int*)CMSG_DATA(cmsg))[0] = fd;
flags = fcntl(proc->socket,F_GETFL,0);
if (flags == -1) {
D("failed to get cntl flags for socket %d: %s\n",
proc->pid, strerror(errno));
goto CloseProcess;
}
if (fcntl(proc->socket, F_SETFL, flags & ~O_NONBLOCK) == -1) {
D("failed to remove O_NONBLOCK flag for socket %d: %s\n",
proc->pid, strerror(errno));
goto CloseProcess;
}
for (;;) {
ret = sendmsg(proc->socket, &msg, 0);
if (ret >= 0)
if (ret >= 0) {
adb_close(fd);
break;
}
if (errno == EINTR)
continue;
D("sending new file descriptor to JDWP %d failed: %s\n",
@ -354,6 +373,12 @@ jdwp_process_event( int socket, unsigned events, void* _proc )
for (n = 1; n < proc->out_count; n++)
proc->out_fds[n-1] = proc->out_fds[n];
if (fcntl(proc->socket, F_SETFL, flags) == -1) {
D("failed to set O_NONBLOCK flag for socket %d: %s\n",
proc->pid, strerror(errno));
goto CloseProcess;
}
if (--proc->out_count == 0)
fdevent_del( proc->fde, FDE_WRITE );
}