* Fork a child process to handle event [eid]. The program [prog] * in directory [dir] is executed with the environment [env]. * * The file descriptor [zfd] is the zevent_fd used to track the * current cursor location within the zevent nvlist. */
| 78 | * current cursor location within the zevent nvlist. |
| 79 | */ |
| 80 | static void |
| 81 | _zed_exec_fork_child(uint64_t eid, const char *dir, const char *prog, |
| 82 | char *env[], int zfd) |
| 83 | { |
| 84 | char path[PATH_MAX]; |
| 85 | int n; |
| 86 | pid_t pid; |
| 87 | int fd; |
| 88 | pid_t wpid; |
| 89 | int status; |
| 90 | |
| 91 | assert(dir != NULL); |
| 92 | assert(prog != NULL); |
| 93 | assert(env != NULL); |
| 94 | assert(zfd >= 0); |
| 95 | |
| 96 | n = snprintf(path, sizeof (path), "%s/%s", dir, prog); |
| 97 | if ((n < 0) || (n >= sizeof (path))) { |
| 98 | zed_log_msg(LOG_WARNING, |
| 99 | "Failed to fork \"%s\" for eid=%llu: %s", |
| 100 | prog, eid, strerror(ENAMETOOLONG)); |
| 101 | return; |
| 102 | } |
| 103 | pid = fork(); |
| 104 | if (pid < 0) { |
| 105 | zed_log_msg(LOG_WARNING, |
| 106 | "Failed to fork \"%s\" for eid=%llu: %s", |
| 107 | prog, eid, strerror(errno)); |
| 108 | return; |
| 109 | } else if (pid == 0) { |
| 110 | (void) umask(022); |
| 111 | if ((fd = open("/dev/null", O_RDWR)) != -1) { |
| 112 | (void) dup2(fd, STDIN_FILENO); |
| 113 | (void) dup2(fd, STDOUT_FILENO); |
| 114 | (void) dup2(fd, STDERR_FILENO); |
| 115 | } |
| 116 | (void) dup2(zfd, ZEVENT_FILENO); |
| 117 | zed_file_close_from(ZEVENT_FILENO + 1); |
| 118 | execle(path, prog, NULL, env); |
| 119 | _exit(127); |
| 120 | } |
| 121 | |
| 122 | /* parent process */ |
| 123 | |
| 124 | zed_log_msg(LOG_INFO, "Invoking \"%s\" eid=%llu pid=%d", |
| 125 | prog, eid, pid); |
| 126 | |
| 127 | /* FIXME: Timeout rogue child processes with sigalarm? */ |
| 128 | |
| 129 | /* |
| 130 | * Wait for child process using WNOHANG to limit |
| 131 | * the time spent waiting to 10 seconds (10,000ms). |
| 132 | */ |
| 133 | for (n = 0; n < 1000; n++) { |
| 134 | wpid = waitpid(pid, &status, WNOHANG); |
| 135 | if (wpid == (pid_t)-1) { |
| 136 | if (errno == EINTR) |
| 137 | continue; |
no test coverage detected