Ticket #382: backendmanager-remotetcp-clean-up-child-pids.patch

File backendmanager-remotetcp-clean-up-child-pids.patch, 2.5 KB (added by Olly Betts, 15 years ago)

Patch which should fix this

  • harness/backendmanager_remotetcp.cc

     
    6969
    7070// We can't dynamically allocate memory for this because it confuses the leak
    7171// detector.  We only have 1-3 child fds open at once anyway, so a fixed size
    72 // array isn't a problem, and linear scanning isn't a problem.
     72// array isn't a problem, and linear scanning isn't a problem either.
    7373struct pid_fd {
    7474    pid_t pid;
    7575    int fd;
     
    7777
    7878static pid_fd pid_to_fd[16];
    7979
     80static void
     81clean_up_fd_for_pid(pid_t pid)
     82{
     83    for (unsigned i = 0; i < sizeof(pid_to_fd) / sizeof(pid_fd); ++i) {
     84        if (pid_to_fd[i].pid == pid) {
     85            int fd = pid_to_fd[i].fd;
     86            pid_to_fd[i].fd = -1;
     87            pid_to_fd[i].pid = 0;
     88            // NB close() *is* safe to use in a signal handler.
     89            close(fd);
     90            break;
     91        }
     92    }
     93}
     94
    8095extern "C" {
     96
    8197static void
    8298on_SIGCHLD(int /*sig*/)
    8399{
    84100    int status;
    85101    pid_t child;
    86102    while ((child = waitpid(-1, &status, WNOHANG)) > 0) {
    87         for (unsigned i = 0; i < sizeof(pid_to_fd) / sizeof(pid_fd); ++i) {
    88             if (pid_to_fd[i].pid == child) {
    89                 int fd = pid_to_fd[i].fd;
    90                 pid_to_fd[i].fd = -1;
    91                 pid_to_fd[i].pid = -1;
    92                 // NB close() *is* safe to use in a signal handler.
    93                 close(fd);
    94                 break;
    95             }
    96         }
     103        clean_up_fd_for_pid(child);
    97104    }
    98105}
     106
    99107}
    100108
    101109static int
     
    104112    int port = DEFAULT_PORT;
    105113
    106114    // We want to be able to get the exit status of the child process we fork
    107     // in xapian-tcpsrv doesn't start listening successfully.
     115    // if xapian-tcpsrv doesn't start listening successfully.
    108116    signal(SIGCHLD, SIG_DFL);
    109117try_next_port:
    110118    string cmd = XAPIAN_TCPSRV" --one-shot --interface "LOCALHOST" --port " + om_tostring(port) + " " + args;
     
    150158        msg += strerror(errno);
    151159        throw msg;
    152160    }
     161
    153162    string output;
    154163    while (true) {
    155164        char buf[256];
    156165        if (fgets(buf, sizeof(buf), fh) == NULL) {
    157166            fclose(fh);
     167            // Wait for the child to exit.
    158168            int status;
    159169            if (waitpid(child, &status, 0) == -1) {
    160170                string msg("waitpid failed: ");
     
    191201    // Find a slot to track the pid->fd mapping in.  If we can't find a slot
    192202    // it just means we'll leak the fd, so don't worry about that too much.
    193203    for (unsigned i = 0; i < sizeof(pid_to_fd) / sizeof(pid_fd); ++i) {
    194         if (pid_to_fd[i].pid == -1) {
     204        if (pid_to_fd[i].pid == 0) {
    195205            pid_to_fd[i].fd = tracked_fd;
    196206            pid_to_fd[i].pid = child;
    197207            break;