Exemple #1
0
static void *mz_proc_thread_signal_worker(void *data) {
  int status;
  int pid, check_pid, is_group;
  sigset_t set;
  Child_Status *unused_status, *prev_unused, *next;

  sigemptyset(&set);
  sigaddset(&set, SIGCHLD);

  while (1) {
    int rc;
    int signalid;

    do {
      rc = sigwait(&set, &signalid);
      if (rc == -1) {
        if (errno != EINTR) {
          fprintf(stderr, "unexpected error from sigwait(): %d\n", errno);
        }
      }
    } while (rc == -1 && errno == EINTR);

    mzrt_mutex_lock(child_status_lock);
    do_group_signal_fds();
    mzrt_mutex_unlock(child_status_lock);

    mzrt_mutex_lock(child_wait_lock);

    unused_status = unused_pid_statuses;
    prev_unused = NULL;

    do {
      if (unused_status) {
        /* See unused_pid_statuses above */
        check_pid = unused_status->pid;
        is_group = 1;
      } else {
        /* We wait only on processes in the same group as Racket,
           because detecting the termination of a group's main process
           disables our ability to terminate all processes in the group. */
        check_pid = 0; /* => processes in the same group as Racket */
        is_group = 0;
      }

      pid = waitpid(check_pid, &status, WNOHANG);

      if (pid == -1) {
        if (errno == EINTR) {
          /* try again */
          pid = 1;
        } else if (!is_group && (errno == ECHILD)) {
          /* no more to check */
        } else {
          fprintf(stderr, "unexpected error from waitpid(%d[%d]): %d\n", 
                  check_pid, is_group, errno);
          if (is_group) {
            prev_unused = unused_status;
            unused_status = unused_status->next;
          } 
        }
      } else if (pid > 0) {
        /* printf("SIGCHILD pid %i with status %i %i\n", pid, status, WEXITSTATUS(status)); */
        if (is_group) {
          next = unused_status->next;
          if (prev_unused)
            prev_unused->next_unused = next;
          else
            unused_pid_statuses = next;
          free(unused_status);
          unused_status = next;
        } else
          add_child_status(pid, status);
      } else {
        if (is_group) {
          prev_unused = unused_status;
          unused_status = unused_status->next;
        }
      }
    } while ((pid > 0) || is_group);

    mzrt_mutex_unlock(child_wait_lock);
  }

  return NULL;
}
Exemple #2
0
static void *thread_signal_worker(void *data)
{
  int status;
  int pid, check_pid, in_group;
  sigset_t set;
  Child_Status *unused_status, *prev_unused, *next;

  sigemptyset(&set);
  sigaddset(&set, SIGCHLD);

  while (1) {
    int rc;
    int signalid;

    do {
      rc = sigwait(&set, &signalid);
      if (rc == -1) {
        if (errno != EINTR) {
          fprintf(stderr, "unexpected error from sigwait(): %d\n", errno);
        }
      }
    } while (rc == -1 && errno == EINTR);

    pthread_mutex_lock(&child_status_lock);
    do_group_signal_fds();
    pthread_mutex_unlock(&child_status_lock);
    
    pthread_mutex_lock(&child_wait_lock);

    unused_status = unused_pid_statuses;
    prev_unused = NULL;

    do {
      if (unused_status) {
        /* See unused_pid_statuses above */
        check_pid = unused_status->pid;
        in_group = 1;
      } else {
        /* We wait only on processes in the same group as the current process,
           because detecting the termination of a group's main process
           disables our ability to terminate all processes in the group. */
        if (pending_children)
          check_pid = 0; /* => processes in the same group as the current process */
        else
          check_pid = -1; /* don't check */
        in_group = 0;
      }

      if (check_pid == -1) {
        pid = -1;
        errno = ECHILD;
      } else
        pid = waitpid(check_pid, &status, WNOHANG);

      if (pid == -1) {
        if (errno == EINTR) {
          /* try again */
          pid = 1;
        } else if (!in_group && (errno == ECHILD)) {
          /* no more to check */
        } else {
          fprintf(stderr, "unexpected error from waitpid(%d[%d]): %d\n", 
                  check_pid, in_group, errno);
          if (in_group) {
            prev_unused = unused_status;
            unused_status = unused_status->next;
          } 
        }
      } else if (pid > 0) {
        /* printf("SIGCHILD pid %i with status %i %i\n", pid, status, WEXITSTATUS(status)); */
        if (in_group) {
          next = unused_status->next_unused;
          if (prev_unused)
            prev_unused->next_unused = next;
          else
            unused_pid_statuses = next;
          free(unused_status);
          unused_status = next;
        } else {
          /* Double-check for pid in unused_pid_statuses, since
             it may have completed between the pid-specific waitpid and the
             non-group waitpid: */
          prev_unused = NULL;
          for (unused_status = unused_pid_statuses; unused_status; unused_status = unused_status->next_unused) {
            if (unused_status->pid == pid)
              break;
            prev_unused = unused_status;
          }
          if (!unused_status) {
            /* not in unused_pid_statuses: */
            add_child_status(pid, extract_child_status(status));
          } else {
            if (prev_unused)
              prev_unused->next_unused = unused_status->next_unused;
            else
              unused_pid_statuses = unused_status->next_unused;
            free(unused_status);
            unused_status = NULL;
          }
        }
      } else {
        if (in_group) {
          prev_unused = unused_status;
          unused_status = unused_status->next_unused;
        }
      }
    } while ((pid > 0) || in_group);

    pthread_mutex_unlock(&child_wait_lock);
  }

  return NULL;
}
Exemple #3
0
static void *mz_proc_thread_signal_worker(void *data) {
  int status;
  int pid, check_pid, is_group;
  sigset_t set;
  Child_Status *group_status, *prev_group, *next;

  sigemptyset(&set);
  sigaddset(&set, SIGCHLD);

  while (1) {
    int rc;
    int signalid;

    do {
      rc = sigwait(&set, &signalid);
      if (rc == -1) {
        if (errno != EINTR) {
          fprintf(stderr, "unexpected error from sigwait(): %d\n", errno);
        }
      }
    } while (rc == -1 && errno == EINTR);

    mzrt_mutex_lock(child_status_lock);
    do_group_signal_fds();
    mzrt_mutex_unlock(child_status_lock);

    mzrt_mutex_lock(child_wait_lock);

    group_status = child_group_statuses;
    prev_group = NULL;

    do {
      if (group_status) {
        check_pid = group_status->pid;
        is_group = 1;
      } else {
        check_pid = 0; /* => processes in the same group as Racket */
        is_group = 0;
      }

      pid = waitpid(check_pid, &status, WNOHANG);

      if (pid == -1) {
        if (errno == EINTR) {
          /* try again */
          pid = 1;
        } else if (!is_group && (errno == ECHILD)) {
          /* no more to check */
        } else {
          fprintf(stderr, "unexpected error from waitpid(%d[%d]): %d\n", 
                  check_pid, is_group, errno);
          if (is_group) {
            prev_group = group_status;
            group_status = group_status->next;
          } 
        }
      } else if (pid > 0) {
        /* printf("SIGCHILD pid %i with status %i %i\n", pid, status, WEXITSTATUS(status)); */
        if (is_group) {
          next = group_status->next;
          if (prev_group)
            prev_group->next_group = next;
          else
            child_group_statuses = next;
          free(group_status);
          group_status = next;
        } else
          add_child_status(pid, status);
      } else {
        if (is_group) {
          prev_group = group_status;
          group_status = group_status->next;
        }
      }
    } while ((pid > 0) || is_group);

    mzrt_mutex_unlock(child_wait_lock);
  }

  return NULL;
}