static void test_atreadeof(abts_case *tc, void *data) { apr_status_t rv; apr_socket_t *sock; apr_socket_t *sock2; apr_proc_t proc; apr_size_t length = STRLEN; char datastr[STRLEN]; int atreadeof = -1; sock = setup_socket(tc); if (!sock) return; launch_child(tc, &proc, "write", p); rv = apr_socket_accept(&sock2, sock, p); APR_ASSERT_SUCCESS(tc, "Problem with receiving connection", rv); /* Check that the remote socket is still open */ rv = apr_socket_atreadeof(sock2, &atreadeof); APR_ASSERT_SUCCESS(tc, "Determine whether at EOF, #1", rv); ABTS_INT_EQUAL(tc, 0, atreadeof); memset(datastr, 0, STRLEN); apr_socket_recv(sock2, datastr, &length); /* Make sure that the server received the data we sent */ ABTS_STR_EQUAL(tc, DATASTR, datastr); ABTS_SIZE_EQUAL(tc, strlen(datastr), wait_child(tc, &proc)); /* The child is dead, so should be the remote socket */ rv = apr_socket_atreadeof(sock2, &atreadeof); APR_ASSERT_SUCCESS(tc, "Determine whether at EOF, #2", rv); ABTS_INT_EQUAL(tc, 1, atreadeof); rv = apr_socket_close(sock2); APR_ASSERT_SUCCESS(tc, "Problem closing connected socket", rv); launch_child(tc, &proc, "close", p); rv = apr_socket_accept(&sock2, sock, p); APR_ASSERT_SUCCESS(tc, "Problem with receiving connection", rv); /* The child closed the socket as soon as it could... */ rv = apr_socket_atreadeof(sock2, &atreadeof); APR_ASSERT_SUCCESS(tc, "Determine whether at EOF, #3", rv); if (!atreadeof) { /* ... but perhaps not yet; wait a moment */ apr_sleep(apr_time_from_msec(5)); rv = apr_socket_atreadeof(sock2, &atreadeof); APR_ASSERT_SUCCESS(tc, "Determine whether at EOF, #4", rv); } ABTS_INT_EQUAL(tc, 1, atreadeof); wait_child(tc, &proc); rv = apr_socket_close(sock2); APR_ASSERT_SUCCESS(tc, "Problem closing connected socket", rv); rv = apr_socket_close(sock); APR_ASSERT_SUCCESS(tc, "Problem closing socket", rv); }
status_t CommandSection::Execute(ReportRequestSet* requests) const { FdBuffer buffer; Fpipe cmdPipe; Fpipe ihPipe; if (!cmdPipe.init() || !ihPipe.init()) { ALOGW("CommandSection '%s' failed to setup pipes", this->name.string()); return -errno; } pid_t cmdPid = fork_execute_cmd((char* const*)mCommand, NULL, &cmdPipe); if (cmdPid == -1) { ALOGW("CommandSection '%s' failed to fork", this->name.string()); return -errno; } pid_t ihPid = fork_execute_incident_helper(this->id, &cmdPipe, &ihPipe); if (ihPid == -1) { ALOGW("CommandSection '%s' failed to fork", this->name.string()); return -errno; } cmdPipe.writeFd().reset(); status_t readStatus = buffer.read(ihPipe.readFd().get(), this->timeoutMs); write_section_stats(requests->sectionStats(this->id), buffer); if (readStatus != NO_ERROR || buffer.timedOut()) { ALOGW("CommandSection '%s' failed to read data from incident helper: %s, timedout: %s", this->name.string(), strerror(-readStatus), buffer.timedOut() ? "true" : "false"); kill_child(cmdPid); kill_child(ihPid); return readStatus; } // Waiting for command here has one trade-off: the failed status of command won't be detected // until buffer timeout, but it has advatage on starting the data stream earlier. status_t cmdStatus = wait_child(cmdPid); status_t ihStatus = wait_child(ihPid); if (cmdStatus != NO_ERROR || ihStatus != NO_ERROR) { ALOGW("CommandSection '%s' abnormal child processes, return status: command: %s, incident " "helper: %s", this->name.string(), strerror(-cmdStatus), strerror(-ihStatus)); return cmdStatus != NO_ERROR ? cmdStatus : ihStatus; } VLOG("CommandSection '%s' wrote %zd bytes in %d ms", this->name.string(), buffer.size(), (int)buffer.durationMs()); status_t err = write_report_requests(this->id, buffer, requests); if (err != NO_ERROR) { ALOGW("CommandSection '%s' failed writing: %s", this->name.string(), strerror(-err)); return err; } return NO_ERROR; }
/** * Prints contents of the given file using cat command. * @param file File to print */ void print_content(char *file) { pid = fork(); if(pid == 0) { execlp("cat", "cat", file, (char*)NULL); perror("Error when executing cat command."); exit(1); } else if(pid < 0) { perror("Error when forking the process."); exit(1); } else { #ifdef DEBUG sprintf(buff, "New process with PID: %d\n", pid); write(1, buff, strlen(buff)); #endif getchar(); wait_child(); } }
static void test_timeout(abts_case *tc, void *data) { apr_status_t rv; apr_socket_t *sock; apr_socket_t *sock2; apr_proc_t proc; int protocol; int exit; sock = setup_socket(tc); if (!sock) return; launch_child(tc, &proc, "read", p); rv = apr_socket_accept(&sock2, sock, p); APR_ASSERT_SUCCESS(tc, "Problem with receiving connection", rv); apr_socket_protocol_get(sock2, &protocol); ABTS_INT_EQUAL(tc, APR_PROTO_TCP, protocol); exit = wait_child(tc, &proc); ABTS_INT_EQUAL(tc, SOCKET_TIMEOUT, exit); /* We didn't write any data, so make sure the child program returns * an error. */ rv = apr_socket_close(sock2); APR_ASSERT_SUCCESS(tc, "Problem closing connected socket", rv); rv = apr_socket_close(sock); APR_ASSERT_SUCCESS(tc, "Problem closing socket", rv); }
int singularity_fork_exec(unsigned int flags, char **argv) { int retval = 1; int i = 0; pid_t child; child = singularity_fork(0); if ( child == 0 ) { while(1) { if ( argv[i] == NULL ) { break; } else if ( i == 128 ) { singularity_message(ERROR, "singularity_fork_exec() ARGV out of bounds\n"); ABORT(255); } singularity_message(DEBUG, "fork argv[%d] = %s\n", i, argv[i]); i++; } singularity_message(VERBOSE, "Running child program: %s\n", argv[0]); if ( execvp(argv[0], argv) < 0 ) { //Flawfinder: ignore singularity_message(ERROR, "Failed to exec program %s: %s\n", argv[0], strerror(errno)); ABORT(255); } } else if ( child > 0 ) { retval = wait_child(); } singularity_message(DEBUG, "Returning from singularity_fork_exec with: %d\n", retval); return(retval); }
static void test_recv(abts_case *tc, void *data) { apr_status_t rv; apr_socket_t *sock; apr_socket_t *sock2; apr_proc_t proc; int protocol; apr_size_t length = STRLEN; char datastr[STRLEN]; sock = setup_socket(tc); if (!sock) return; launch_child(tc, &proc, "write", p); rv = apr_socket_accept(&sock2, sock, p); APR_ASSERT_SUCCESS(tc, "Problem with receiving connection", rv); apr_socket_protocol_get(sock2, &protocol); ABTS_INT_EQUAL(tc, APR_PROTO_TCP, protocol); memset(datastr, 0, STRLEN); apr_socket_recv(sock2, datastr, &length); /* Make sure that the server received the data we sent */ ABTS_STR_EQUAL(tc, DATASTR, datastr); ABTS_SIZE_EQUAL(tc, strlen(datastr), wait_child(tc, &proc)); rv = apr_socket_close(sock2); APR_ASSERT_SUCCESS(tc, "Problem closing connected socket", rv); rv = apr_socket_close(sock); APR_ASSERT_SUCCESS(tc, "Problem closing socket", rv); }
static void test_send(abts_case *tc, void *data) { apr_status_t rv; apr_socket_t *sock; apr_socket_t *sock2; apr_proc_t proc; int protocol; apr_size_t length; sock = setup_socket(tc); if (!sock) return; launch_child(tc, &proc, "read", p); rv = apr_socket_accept(&sock2, sock, p); APR_ASSERT_SUCCESS(tc, "Problem with receiving connection", rv); apr_socket_protocol_get(sock2, &protocol); ABTS_INT_EQUAL(tc, APR_PROTO_TCP, protocol); length = strlen(DATASTR); apr_socket_send(sock2, DATASTR, &length); /* Make sure that the client received the data we sent */ ABTS_SIZE_EQUAL(tc, strlen(DATASTR), wait_child(tc, &proc)); rv = apr_socket_close(sock2); APR_ASSERT_SUCCESS(tc, "Problem closing connected socket", rv); rv = apr_socket_close(sock); APR_ASSERT_SUCCESS(tc, "Problem closing socket", rv); }
int main(int argc, char ** argv) { //初始化两个信号集,一个只有usr1,一个只有usr2 sigemptyset(&t_sigset_usr); sigemptyset(&t_sigset_old); sigemptyset(&t_sigset_zero); sigaddset(&t_sigset_usr, SIGUSR1); sigaddset(&t_sigset_usr, SIGUSR2); //注册信号处理程序, signal(SIGUSR1, do_sig_usr); signal(SIGUSR2, do_sig_usr); //父进程阻塞usr信号 sigprocmask(SIG_SETMASK, &t_sigset_usr, NULL ); pid_t child_pid; //父进程fork一个子进程出来 child_pid = fork(); if (child_pid == 0) { //子进程,从2开始写 num = 2; //注册信号处理程序, signal(SIGUSR1, do_sig_usr); signal(SIGUSR2, do_sig_usr); //子进程阻塞usr信号 sigprocmask(SIG_SETMASK, &t_sigset_usr, NULL ); //子进程准备完毕,通知父进程去写 tell_parent(); while (1) { //始终等待父进程唤醒 wait_parent(); write_num_to_file(); tell_parent(); } } else { //父进程 while (1) { //始终等待子进程唤醒 wait_child(); write_num_to_file(); tell_child(child_pid); } } //子进程写入数据,并且告知父进程,然后投入睡眠,等待父进程唤醒 //父进程等待子进程 exit(0); }
static int handle_child_error(int pid) { int ret = wait_child(pid); if (ret < 0) { error_msg("waitpid: %s", strerror(errno)); } else if (ret >= 256) { error_msg("Child received signal %d", ret >> 8); } else if (ret) {
int wait_command(int pid) { if (wait_child(pid) < 0) { printf("Fatal error in process.\n"); return (-1); } return (0); }
status_t FileSection::Execute(ReportRequestSet* requests) const { // read from mFilename first, make sure the file is available // add O_CLOEXEC to make sure it is closed when exec incident helper unique_fd fd(open(mFilename, O_RDONLY | O_CLOEXEC)); if (fd.get() == -1) { ALOGW("FileSection '%s' failed to open file", this->name.string()); return this->deviceSpecific ? NO_ERROR : -errno; } FdBuffer buffer; Fpipe p2cPipe; Fpipe c2pPipe; // initiate pipes to pass data to/from incident_helper if (!p2cPipe.init() || !c2pPipe.init()) { ALOGW("FileSection '%s' failed to setup pipes", this->name.string()); return -errno; } pid_t pid = fork_execute_incident_helper(this->id, &p2cPipe, &c2pPipe); if (pid == -1) { ALOGW("FileSection '%s' failed to fork", this->name.string()); return -errno; } // parent process status_t readStatus = buffer.readProcessedDataInStream(fd.get(), std::move(p2cPipe.writeFd()), std::move(c2pPipe.readFd()), this->timeoutMs, mIsSysfs); write_section_stats(requests->sectionStats(this->id), buffer); if (readStatus != NO_ERROR || buffer.timedOut()) { ALOGW("FileSection '%s' failed to read data from incident helper: %s, timedout: %s", this->name.string(), strerror(-readStatus), buffer.timedOut() ? "true" : "false"); kill_child(pid); return readStatus; } status_t ihStatus = wait_child(pid); if (ihStatus != NO_ERROR) { ALOGW("FileSection '%s' abnormal child process: %s", this->name.string(), strerror(-ihStatus)); return ihStatus; } VLOG("FileSection '%s' wrote %zd bytes in %d ms", this->name.string(), buffer.size(), (int)buffer.durationMs()); status_t err = write_report_requests(this->id, buffer, requests); if (err != NO_ERROR) { ALOGW("FileSection '%s' failed writing: %s", this->name.string(), strerror(-err)); return err; } return NO_ERROR; }
/** * Kills the main process and its child, if it's not dead already. * @param s Signal identifier */ void kill_all(int s) { sprintf(buff, "Time is over\n"); write(1, buff, strlen(buff)); if(pid != -1) { kill(pid, SIGKILL); wait_child(); } exit(0); }
void singularity_fork_run(unsigned int flags) { pid_t child; int retval; child = singularity_fork(flags); if ( child == 0 ) { return; } else if ( child > 0 ) { retval = wait_child(); exit(retval); } }
char *thread_line(int line, t_screen *screen, t_scene *scene, int (*calc_method)(t_screen *screen, t_scene *, double, double)) { static int start = 1; int num; if (start) { init_thread(screen, scene); wait_child(scene->thread, &screen->img); } start = 0; num = -1; while (++num < screen->img.thread_num) { scene->thread[num].y = line; scene->thread[num].calc_method = calc_method; X(write(scene->thread[num].pipein[1], "a", 1)); } wait_child(scene->thread, &screen->img); return (screen->img.data + line * screen->img.sizeline); }
static void test_wait_child_wait3_zero_return() { setup(); expect_not_value( mock_wait3, status, NULL ); expect_value( mock_wait3, options, WNOHANG ); expect_value( mock_wait3, rusage, NULL ); mock_wait3_status = 0; will_return( mock_wait3, 0 ); wait_child(); teardown(); }
int Pclose(FILE *ptr) { int i; sigset_t nset, oset; i = file_pid(ptr); unregister_file(ptr); (void)fclose(ptr); (void)sigemptyset(&nset); (void)sigaddset(&nset, SIGINT); (void)sigaddset(&nset, SIGHUP); (void)sigprocmask(SIG_BLOCK, &nset, &oset); i = wait_child(i); (void)sigprocmask(SIG_SETMASK, &oset, NULL); return (i); }
int ft_run_exe(char *path, char **options, t_dlist *list) { pid_t pid; if (path == NULL) return (0); pid = fork(); if (pid > 0) wait_child(); if (pid == 0) { execve(path, options, ft_tab_from_list(list)); ft_putstr("error execve"); exit(0); } return (EXIT_SUCCESS); }
/* * Interactively dump core on "core" */ int core(void) { int pid; switch (pid = fork()) { case -1: warn("fork"); return (1); case 0: abort(); _exit(1); } printf("Okie dokie"); (void)fflush(stdout); wait_child(pid); if (WIFSIGNALED(wait_status) && WCOREDUMP(wait_status)) printf(" -- Core dumped.\n"); else printf(" -- Can't dump core.\n"); return (0); }
int parent_process() { int shm_id; void* shm_ptr = NULL; shm_id = shmget(SHM_KEY, SHM_SIZE, IPC_CREAT | IPC_EXCL | SHM_MODE); if(-1 == shm_id) { printf("[P]Fail to create shm, errno: %d, errmsg: %s\n", errno, strerror(errno)); return -1; } shm_ptr = shmat(shm_id, 0, 0); if((void*)-1 == shm_ptr) { printf("[P]Fail to attach to shm, errno: %d, errmsg: %s\n", errno, strerror(errno)); return -1; } char buf[1024] = "String from parent."; memcpy(shm_ptr, (const void*)buf, strlen(buf)); if(-1 == tell_child()) { printf("[P]fail to tell_child, process exit\n"); shmdt(shm_ptr); shmctl(shm_id, IPC_RMID, 0); _exit(0); } if(-1 == wait_child()) { printf("[P]fail to wait_child, process exit\n"); shmdt(shm_ptr); shmctl(shm_id, IPC_RMID, 0); _exit(0); } shmctl(shm_id, IPC_RMID, 0); return 0; }
/* * Interactively dump core on "core" */ int core(void *v) { pid_t pid; extern int wait_status; switch (pid = vfork()) { case -1: warn("vfork"); return(1); case 0: abort(); _exit(1); } //fputs("Okie dokie", stdout); //fflush(stdout); wait_child(pid); if (WIFSIGNALED(wait_status) && WCOREDUMP(wait_status)) puts(" -- Core dumped."); else puts(" -- Can't dump core."); return(0); }
status_t TombstoneSection::BlockingCall(int pipeWriteFd) const { std::unique_ptr<DIR, decltype(&closedir)> proc(opendir("/proc"), closedir); if (proc.get() == nullptr) { ALOGE("opendir /proc failed: %s\n", strerror(errno)); return -errno; } const std::set<int> hal_pids = get_interesting_hal_pids(); ProtoOutputStream proto; struct dirent* d; status_t err = NO_ERROR; while ((d = readdir(proc.get()))) { int pid = atoi(d->d_name); if (pid <= 0) { continue; } const std::string link_name = android::base::StringPrintf("/proc/%d/exe", pid); std::string exe; if (!android::base::Readlink(link_name, &exe)) { ALOGE("Can't read '%s': %s\n", link_name.c_str(), strerror(errno)); continue; } bool is_java_process; if (exe == "/system/bin/app_process32" || exe == "/system/bin/app_process64") { if (mType != "java") continue; // Don't bother dumping backtraces for the zygote. if (IsZygote(pid)) { VLOG("Skipping Zygote"); continue; } is_java_process = true; } else if (should_dump_native_traces(exe.c_str())) { if (mType != "native") continue; is_java_process = false; } else if (hal_pids.find(pid) != hal_pids.end()) { if (mType != "hal") continue; is_java_process = false; } else { // Probably a native process we don't care about, continue. VLOG("Skipping %d", pid); continue; } Fpipe dumpPipe; if (!dumpPipe.init()) { ALOGW("TombstoneSection '%s' failed to setup dump pipe", this->name.string()); err = -errno; break; } const uint64_t start = Nanotime(); pid_t child = fork(); if (child < 0) { ALOGE("Failed to fork child process"); break; } else if (child == 0) { // This is the child process. dumpPipe.readFd().reset(); const int ret = dump_backtrace_to_file_timeout( pid, is_java_process ? kDebuggerdJavaBacktrace : kDebuggerdNativeBacktrace, is_java_process ? 5 : 20, dumpPipe.writeFd().get()); if (ret == -1) { if (errno == 0) { ALOGW("Dumping failed for pid '%d', likely due to a timeout\n", pid); } else { ALOGE("Dumping failed for pid '%d': %s\n", pid, strerror(errno)); } } dumpPipe.writeFd().reset(); _exit(EXIT_SUCCESS); } dumpPipe.writeFd().reset(); // Parent process. // Read from the pipe concurrently to avoid blocking the child. FdBuffer buffer; err = buffer.readFully(dumpPipe.readFd().get()); // Wait on the child to avoid it becoming a zombie process. status_t cStatus = wait_child(child); if (err != NO_ERROR) { ALOGW("TombstoneSection '%s' failed to read stack dump: %d", this->name.string(), err); dumpPipe.readFd().reset(); break; } if (cStatus != NO_ERROR) { ALOGE("[%s] child had an issue: %s\n", this->name.string(), strerror(-cStatus)); } auto dump = std::make_unique<char[]>(buffer.size()); auto iterator = buffer.data(); int i = 0; while (iterator.hasNext()) { dump[i] = iterator.next(); i++; } uint64_t token = proto.start(android::os::BackTraceProto::TRACES); proto.write(android::os::BackTraceProto::Stack::PID, pid); proto.write(android::os::BackTraceProto::Stack::DUMP, dump.get(), i); proto.write(android::os::BackTraceProto::Stack::DUMP_DURATION_NS, static_cast<long long>(Nanotime() - start)); proto.end(token); dumpPipe.readFd().reset(); } if (!proto.flush(pipeWriteFd) && errno == EPIPE) { ALOGE("[%s] wrote to a broken pipe\n", this->name.string()); if (err != NO_ERROR) { return EPIPE; } } return err; }
status_t GZipSection::Execute(ReportRequestSet* requests) const { // Reads the files in order, use the first available one. int index = 0; unique_fd fd; while (mFilenames[index] != NULL) { fd.reset(open(mFilenames[index], O_RDONLY | O_CLOEXEC)); if (fd.get() != -1) { break; } ALOGW("GZipSection failed to open file %s", mFilenames[index]); index++; // look at the next file. } VLOG("GZipSection is using file %s, fd=%d", mFilenames[index], fd.get()); if (fd.get() == -1) { ALOGW("GZipSection %s can't open all the files", this->name.string()); return NO_ERROR; // e.g. LAST_KMSG will reach here in user build. } FdBuffer buffer; Fpipe p2cPipe; Fpipe c2pPipe; // initiate pipes to pass data to/from gzip if (!p2cPipe.init() || !c2pPipe.init()) { ALOGW("GZipSection '%s' failed to setup pipes", this->name.string()); return -errno; } pid_t pid = fork_execute_cmd((char* const*)GZIP, &p2cPipe, &c2pPipe); if (pid == -1) { ALOGW("GZipSection '%s' failed to fork", this->name.string()); return -errno; } // parent process // construct Fdbuffer to output GZippedfileProto, the reason to do this instead of using // ProtoOutputStream is to avoid allocation of another buffer inside ProtoOutputStream. EncodedBuffer* internalBuffer = buffer.getInternalBuffer(); internalBuffer->writeHeader((uint32_t)GZippedFileProto::FILENAME, WIRE_TYPE_LENGTH_DELIMITED); size_t fileLen = strlen(mFilenames[index]); internalBuffer->writeRawVarint32(fileLen); for (size_t i = 0; i < fileLen; i++) { internalBuffer->writeRawByte(mFilenames[index][i]); } internalBuffer->writeHeader((uint32_t)GZippedFileProto::GZIPPED_DATA, WIRE_TYPE_LENGTH_DELIMITED); size_t editPos = internalBuffer->wp()->pos(); internalBuffer->wp()->move(8); // reserve 8 bytes for the varint of the data size. size_t dataBeginAt = internalBuffer->wp()->pos(); VLOG("GZipSection '%s' editPos=%zd, dataBeginAt=%zd", this->name.string(), editPos, dataBeginAt); status_t readStatus = buffer.readProcessedDataInStream( fd.get(), std::move(p2cPipe.writeFd()), std::move(c2pPipe.readFd()), this->timeoutMs, isSysfs(mFilenames[index])); write_section_stats(requests->sectionStats(this->id), buffer); if (readStatus != NO_ERROR || buffer.timedOut()) { ALOGW("GZipSection '%s' failed to read data from gzip: %s, timedout: %s", this->name.string(), strerror(-readStatus), buffer.timedOut() ? "true" : "false"); kill_child(pid); return readStatus; } status_t gzipStatus = wait_child(pid); if (gzipStatus != NO_ERROR) { ALOGW("GZipSection '%s' abnormal child process: %s", this->name.string(), strerror(-gzipStatus)); return gzipStatus; } // Revisit the actual size from gzip result and edit the internal buffer accordingly. size_t dataSize = buffer.size() - dataBeginAt; internalBuffer->wp()->rewind()->move(editPos); internalBuffer->writeRawVarint32(dataSize); internalBuffer->copy(dataBeginAt, dataSize); VLOG("GZipSection '%s' wrote %zd bytes in %d ms, dataSize=%zd", this->name.string(), buffer.size(), (int)buffer.durationMs(), dataSize); status_t err = write_report_requests(this->id, buffer, requests); if (err != NO_ERROR) { ALOGW("GZipSection '%s' failed writing: %s", this->name.string(), strerror(-err)); return err; } return NO_ERROR; }
int main(int argc, char *argv[]) { struct pidfh *pfh = NULL; sigset_t mask, oldmask; int ch, nochdir, noclose, restart; const char *pidfile, *user; pid_t otherpid, pid; nochdir = noclose = 1; restart = 0; pidfile = user = NULL; while ((ch = getopt(argc, argv, "-cfp:ru:")) != -1) { switch (ch) { case 'c': nochdir = 0; break; case 'f': noclose = 0; break; case 'p': pidfile = optarg; break; case 'r': restart = 1; break; case 'u': user = optarg; break; default: usage(); } } argc -= optind; argv += optind; if (argc == 0) usage(); pfh = NULL; /* * Try to open the pidfile before calling daemon(3), * to be able to report the error intelligently */ if (pidfile != NULL) { pfh = pidfile_open(pidfile, 0600, &otherpid); if (pfh == NULL) { if (errno == EEXIST) { errx(3, "process already running, pid: %d", otherpid); } err(2, "pidfile ``%s''", pidfile); } } if (daemon(nochdir, noclose) == -1) err(1, NULL); /* * If the pidfile or restart option is specified the daemon * executes the command in a forked process and wait on child * exit to remove the pidfile or restart the command. Normally * we don't want the monitoring daemon to be terminated * leaving the running process and the stale pidfile, so we * catch SIGTERM and forward it to the children expecting to * get SIGCHLD eventually. */ pid = -1; if (pidfile != NULL || restart) { /* * Restore default action for SIGTERM in case the * parent process decided to ignore it. */ if (signal(SIGTERM, SIG_DFL) == SIG_ERR) err(1, "signal"); /* * Because SIGCHLD is ignored by default, setup dummy handler * for it, so we can mask it. */ if (signal(SIGCHLD, dummy_sighandler) == SIG_ERR) err(1, "signal"); /* * Block interesting signals. */ sigemptyset(&mask); sigaddset(&mask, SIGTERM); sigaddset(&mask, SIGCHLD); if (sigprocmask(SIG_SETMASK, &mask, &oldmask) == -1) err(1, "sigprocmask"); /* * Try to protect against pageout kill. Ignore the * error, madvise(2) will fail only if a process does * not have superuser privileges. */ (void)madvise(NULL, 0, MADV_PROTECT); restart: /* * Spawn a child to exec the command, so in the parent * we could wait for it to exit and remove pidfile. */ pid = fork(); if (pid == -1) { pidfile_remove(pfh); err(1, "fork"); } } if (pid <= 0) { if (pid == 0) { /* Restore old sigmask in the child. */ if (sigprocmask(SIG_SETMASK, &oldmask, NULL) == -1) err(1, "sigprocmask"); } /* Now that we are the child, write out the pid. */ pidfile_write(pfh); if (user != NULL) restrict_process(user); execvp(argv[0], argv); /* * execvp() failed -- report the error. The child is * now running, so the exit status doesn't matter. */ err(1, "%s", argv[0]); } setproctitle("%s[%d]", argv[0], pid); if (wait_child(pid, &mask) == 0 && restart) { sleep(1); goto restart; } pidfile_remove(pfh); exit(0); /* Exit status does not matter. */ }
int main(int argc, char const *argv[]) { char buf[MAXSIZE]={'\0'}; char buf_r[MAXSIZE]={'\0'}; int fd[2]; pipe(fd); signal(SIGPIPE,fun); pid_t pid; int len = 0; int nr = 0; int sum = 0; int nread,len_r; //signal tongbu tell_wait(); //sgnal tongbu pid = fork(); if (pid <0) { perror("error"); /* code */ }else if (pid == 0) { /* code */ wait_father(); printf("the child process.....%d\n",getpid()); printf("the child process's father process id:%d\n",getppid()); close(fd[1]); while((nread = read(fd[0],buf,sizeof(buf)))!=-1){ tell_father(pid); setbuf(stdout,NULL);//set the stdout no buffer printf("the child write to stdout:"); write(STDOUT_FILENO,buf,nread); //the write to stdout is bo bug ,but the printf is bug len_r = strlen(buf); printf("len_r :%d\n",len_r ); for (int i = 0; (buf[i]!='\n'); i++) { sum +=i; printf("sum:%d\n",sum ); printf("buf[%d]:%c\t",i,buf[i] ); if (buf[i]=='\0') { break; } } printf("\n"); // printf("child read:%s\n",buf ); //the sentence is bug ,it is of buffer and \n } exit(0); }else{ // sleep(3); tell_child(pid); printf("the father process.......%d\n",getpid()); printf("the father process's father process id:%d\n",getppid()); close(fd[0]);//the sentense to invlole the SIGPIPE take place char * p = NULL; /* code */ while((p = fgets(buf,sizeof(buf),stdin))!=NULL){ len = strlen(buf); printf("the length :%d\n",len ); if (p[len] =='\n') { printf("%c\n",p[len -1] ); len--; p[len ] = '\0'; /* code */ } if (p[len -1] == '\0') { printf("fgets read the null in buffer\n"); /* code */ } fflush(stdin); int n = write(fd[1],buf,len); if (n==-1) { if (errno = EINTR) { printf("the failed is SIGINT\n"); /* code */ } printf("err write\n"); }else printf("father write to pipe successfully\n"); wait_child(); } int status; // the waitpid 's return val is the son process pid,if it wait to catch the son state successfully int ret = waitpid(pid,&status,0); if (ret == -1) { printf("wait child failed\n"); /* code */ }else printf("the wait id:%d\n", ret);//the ret == son pid } return 0; }
int main(int argc, char *argv[]) { int i,n_children,k,pid[MAX]; // Print all argument (debug purpose) printf("Arguments:\n"); for (i = 0; i < argc; i++) printf("[%d]:%s\n", i,argv[i]); //Check number of arguments if(argc < 2){ printf("Illegal number of parameters\n"); exit(1); } //Check argument is digit if(!isdigit(argv[1][0])){ printf("%d parameter is not digit\n",argv[1][0]); exit(1); } n_children = atoi(argv[1]); k = (int)n_children/2; printf("n_children = %d\n", n_children); printf("k = %d\n", k); printf("----- start program -----\n"); for (i = 0; i < n_children; ++i) { //printf("about to create child [%d]\n", i); pid[i] = fork(); if (pid[i] == 0) // child { printf("child:pid - [%d][%d]\n",i,getpid()); if (i<k){ printf("\tchild[%d] about to start wait\n",getpid()); wait_for_signal(); } else { printf("\tchild[%d] wait 5 sec\n",getpid()); sleep_and_terminate(); } } else if (pid[i] > 0) { //father } else //Errors { perror("Impossibile fare la fork():"); exit(2); } } for (i = 0; i < k; ++i) { kill(pid[i],SIGUSR1); } for (i = 0; i < n_children; ++i) { wait_child(); } return 0; }
int main(int argc, char *argv[]) { euca_opts euca_args; euca_opts *args = &euca_args; java_home_t *data = NULL; int status = 0; pid_t pid = 0; uid_t uid = 0; gid_t gid = 0; int i; if (arguments(argc, argv, args) != 0) exit(1); debug = args->debug_flag; set_output(GETARG(args, out), GETARG(args, err)); if (args->kill_flag == 1) return stop_child(args); if (checkuser(GETARG(args, user), &uid, &gid) == 0) return 1; for (i = 0; i < args->java_home_given; ++i) { __debug("Trying user supplied java home: %s", args->java_home_arg[i]); data = get_java_home(args->java_home_arg[i]); if (data != NULL) { break; } } char* java_home_env = getenv("JAVA_HOME"); if (data == NULL && java_home_env != NULL) { __debug("Trying environment JAVA_HOME: %s", java_home_env); data = get_java_home(java_home_env); } if (data == NULL && !args->java_home_given && args->java_home_arg[0] != NULL && CHECK_ISDIR(args->java_home_arg[0])) { __debug("Trying built-in java home: %s", args->java_home_arg[0]); data = get_java_home(args->java_home_arg[0]); } if (data == NULL && CHECK_ISREG("/usr/bin/java")) { char * javapath = (char *) calloc(PATH_MAX, sizeof(char)); javapath = realpath("/usr/bin/java", javapath); if (javapath != NULL) { javapath[strlen(javapath)-strlen("jre/bin/java")] = '\0'; __debug("Trying system java home: %s", javapath); data = get_java_home(javapath); } } if (data == NULL) { __error("Cannot locate Java Home"); return 1; } int x; if (debug == 1) { __debug("+-- DUMPING JAVA HOME STRUCTURE ------------------------"); __debug("| Java Home: \"%s\"", PRINT_NULL(data->path)); __debug("| Found JVMs: %d", data->jnum); for (x = 0; x < data->jnum; x++) { jvm_info_t *jvm = data->jvms[x]; __debug("| JVM Name: \"%s\"", PRINT_NULL(jvm->name)); __debug("| \"%s\"", PRINT_NULL(jvm->libjvm_path)); } __debug("+-------------------------------------------------------"); } if (strcmp(argv[0], "eucalyptus-cloud") != 0) { char *oldpath = getenv("LD_LIBRARY_PATH"), *libf = java_library(args, data); char *old = argv[0], buf[32768], *tmp = NULL, *p1 = NULL, *p2 = NULL; p1 = strdup(libf); tmp = strrchr(p1, '/'); if (tmp != NULL) tmp[0] = '\0'; p2 = strdup(p1); tmp = strrchr(p2, '/'); if (tmp != NULL) tmp[0] = '\0'; if (oldpath == NULL) snprintf(buf, 32768, "%s:%s:%s/bin/linux-x64", p1, p2, GETARG(args, profiler_home)); else snprintf(buf, 32768, "%s:%s:%s:%s/bin/linux-x64", oldpath, p1, p2, GETARG(args, profiler_home)); tmp = strdup(buf); setenv("LD_LIBRARY_PATH", tmp, 1); __debug("Invoking w/ LD_LIBRARY_PATH=%s", getenv("LD_LIBRARY_PATH")); argv[0] = "eucalyptus-cloud"; execve(old, argv, environ); __error("Cannot execute process"); return 1; } __debug("Running w/ LD_LIBRARY_PATH=%s", getenv("LD_LIBRARY_PATH")); if (args->fork_flag) { pid = fork(); __die((pid == -1), "Cannot detach from parent process"); if (pid != 0) return wait_child(args, pid); setsid(); } while ((pid = fork()) != -1) { if (pid == 0) exit(child(args, data, uid, gid)); child_pid = pid; signal(SIGHUP, controller); signal(SIGTERM, controller); signal(SIGINT, controller); while (waitpid(-1, &status, 0) != pid) ; if (WIFEXITED(status)) { status = WEXITSTATUS(status); __debug("Eucalyptus exited with status: %d", status); unlink(GETARG(args, pidfile)); if (status == EUCA_RET_RELOAD) { __debug("Reloading service."); continue; } else if (status == 0) { __debug("Service shut down cleanly."); return 0; } __error("Service exit with a return value of %d.", status); return 1; } else { perror("Service did not exit cleanly."); __error("Service did not exit cleanly: exit value=%d.", status); return 1; } } __error("Cannot decouple controller/child processes"); return 1; }
int main( int argc, char *argv[ ] ) { euca_opts euca_args; euca_opts *args = &euca_args; java_home_t *data = NULL; int status = 0; pid_t pid = 0; uid_t uid = 0; gid_t gid = 0; if( arguments( argc, argv, args ) != 0 ) exit( 1 ); debug = args->verbose_flag || args->debug_flag; if( args->stop_flag == 1 ) return stop_child( args ); if( checkuser( GETARG( args, user ), &uid, &gid ) == 0 ) return 1; char* java_home_user = GETARG(args,java_home); char* java_home_env = getenv( "JAVA_HOME" ); if( java_home_user != NULL ) { __debug("Trying user supplied java home: %s", java_home_user); data = get_java_home(java_home_user); } if( data == NULL && java_home_env != NULL ) { __debug("Trying environment JAVA_HOME: %s", java_home_env); data = get_java_home(java_home_env); } __debug("TODO: loop through common locations for JVMs here."); if( data == NULL ) { __error( "Cannot locate Java Home" ); return 1; } int x; if( debug == 1 ) { __debug( "+-- DUMPING JAVA HOME STRUCTURE ------------------------" ); __debug( "| Java Home: \"%s\"", PRINT_NULL( data->path ) ); __debug( "| Found JVMs: %d", data->jnum ); for( x = 0; x < data->jnum; x++ ) { jvm_info_t *jvm = data->jvms[ x ]; __debug( "| JVM Name: \"%s\"", PRINT_NULL( jvm->name ) ); __debug( "| \"%s\"", PRINT_NULL( jvm->libjvm_path ) ); } __debug( "+-------------------------------------------------------" ); } if( strcmp( argv[ 0 ], "eucalyptus-cloud" ) != 0 ) { char *oldpath = getenv( "LD_LIBRARY_PATH" ),*libf = java_library( args, data ); char *old = argv[ 0 ],buf[ 32768 ],*tmp = NULL,*p1 = NULL,*p2 = NULL; p1 = strdup( libf ); tmp = strrchr( p1, '/' ); if( tmp != NULL ) tmp[ 0 ] = '\0'; p2 = strdup( p1 ); tmp = strrchr( p2, '/' ); if( tmp != NULL ) tmp[ 0 ] = '\0'; if( oldpath == NULL ) snprintf( buf, 32768, "%s:%s:%s/bin/linux-x64", p1, p2, GETARG(args,profiler_home) ); else snprintf( buf, 32768, "%s:%s:%s:%s/bin/linux-x64", oldpath, p1, p2, GETARG(args,profiler_home) ); tmp = strdup( buf ); setenv( "LD_LIBRARY_PATH", tmp, 1 ); __debug( "Invoking w/ LD_LIBRARY_PATH=%s", getenv( "LD_LIBRARY_PATH" ) ); argv[ 0 ] = "eucalyptus-cloud"; execve( old, argv, environ ); __error( "Cannot execute process" ); return 1; } __debug( "Running w/ LD_LIBRARY_PATH=%s", getenv( "LD_LIBRARY_PATH" ) ); if(args->fork_flag) { pid = fork( ); __die(( pid == -1 ),"Cannot detach from parent process" ); if( pid != 0 ) return wait_child( args, pid ); setsid( ); } set_output(GETARG(args,out), GETARG(args,err)); while( ( pid = fork( ) ) != -1 ) { if( pid == 0 ) exit( child( args, data, uid, gid ) ); child_pid = pid; signal( SIGHUP, controller ); signal( SIGTERM, controller ); signal( SIGINT, controller ); while( waitpid( pid, &status, 0 ) != pid ); if( WIFEXITED( status ) ) { status = WEXITSTATUS( status ); __debug( "Eucalyptus exited with status: %d", status ); if( status != 122 ) unlink( GETARG( args, pidfile ) ); if( status == 123 ) { __debug( "Reloading service" ); continue; } if( status == 0 ) { __debug( "Service shut down" ); return 0; } __error( "Service exit with a return value of %d", status ); return 1; } else { __error( "Service did not exit cleanly exit value %d", status ); return 1; } } __error( "Cannot decouple controller/child processes" ); return 1; }
static int stop_child( euca_opts *args ) { int pid = __get_pid( GETARG(args,pidfile) ); if( pid <= 0 ) return -1; kill( pid, SIGTERM ); return wait_child(args,pid); }
int wait_all_childs() { int failures = 0; while (forked_childs > 0) failures += wait_child(); return failures; }
/* * Evaluate the string given as a new mailbox name. * Supported meta characters: * % for my system mail box * %user for user's system mail box * # for previous file * & invoker's mbox file * +file file in folder directory * any shell meta character * Return the file name as a dynamic string. */ char * expand(char *name) { char xname[PATHSIZE]; char cmdbuf[PATHSIZE]; /* also used for file names */ int pid, l; char *cp, *sh; int pivec[2]; struct stat sbuf; /* * The order of evaluation is "%" and "#" expand into constants. * "&" can expand into "+". "+" can expand into shell meta characters. * Shell meta characters expand into constants. * This way, we make no recursive expansion. */ switch (*name) { case '%': findmail(name[1] ? name + 1 : myname, xname, sizeof(xname)); return (savestr(xname)); case '#': if (name[1] != 0) break; if (prevfile[0] == 0) { printf("No previous file\n"); return (NULL); } return (savestr(prevfile)); case '&': if (name[1] == 0 && (name = value("MBOX")) == NULL) name = "~/mbox"; /* fall through */ } if (name[0] == '+' && getfold(cmdbuf, sizeof(cmdbuf)) >= 0) { (void)snprintf(xname, sizeof(xname), "%s/%s", cmdbuf, name + 1); name = savestr(xname); } /* catch the most common shell meta character */ if (name[0] == '~' && homedir != NULL && (name[1] == '/' || name[1] == '\0')) { (void)snprintf(xname, sizeof(xname), "%s%s", homedir, name + 1); name = savestr(xname); } if (!strpbrk(name, "~{[*?$`'\"\\")) return (name); if (pipe(pivec) < 0) { warn("pipe"); return (name); } (void)snprintf(cmdbuf, sizeof(cmdbuf), "echo %s", name); if ((sh = value("SHELL")) == NULL) sh = _PATH_CSHELL; pid = start_command(sh, 0, -1, pivec[1], "-c", cmdbuf, NULL); if (pid < 0) { (void)close(pivec[0]); (void)close(pivec[1]); return (NULL); } (void)close(pivec[1]); l = read(pivec[0], xname, BUFSIZ); (void)close(pivec[0]); if (wait_child(pid) < 0 && WIFSIGNALED(wait_status) && WTERMSIG(wait_status) != SIGPIPE) { fprintf(stderr, "\"%s\": Expansion failed.\n", name); return (NULL); } if (l < 0) { warn("read"); return (NULL); } if (l == 0) { fprintf(stderr, "\"%s\": No match.\n", name); return (NULL); } if (l == BUFSIZ) { fprintf(stderr, "\"%s\": Expansion buffer overflow.\n", name); return (NULL); } xname[l] = '\0'; for (cp = &xname[l-1]; *cp == '\n' && cp > xname; cp--) ; cp[1] = '\0'; if (strchr(xname, ' ') && stat(xname, &sbuf) < 0) { fprintf(stderr, "\"%s\": Ambiguous.\n", name); return (NULL); } return (savestr(xname)); }