int status, w;
w = waitpid(p, &status, WUNTRACED | WCONTINUED);
if (w != -1 && WIFEXITED(status)) { exit(WEXITSTATUS(status));
}
exit(EXIT_FAILURE);
}
argv += nopt;
argc -= nopt; /* now argv points to the executable */
if (argc == 0) { // -e turned echoing off // -w wait until signaled (SIGCONT) before executing a process // -p define pts_name to use instead of opening a new one // --env passes additional environment variable to a program // in NAME=VALUE form. For multiple variables multiple // --env options should be used. // --no-pty do not allocate pseudo-terminal - just execute a program // if --no-pty is used, -p/-w has no effect // --readenv start a new process in an environment. recorded in a // specified file. // --dumpenv record current environment in a specified file // --report record process' and exit status information into // specified file
err_quit("\n\n" "usage: %s [-e] [--no-pty] [-w] [-p pts_name] [--set-erase-key]\n" "\t\t[--readenv env_file] [[--env NAME=VALUE] ...] [--dir dir]\n" "\t\t[--redirect-error] [--report report_file] program [ arg ... ]\n\n" "\t-e\t\t turn echoing off\n" "\t-w\t\t wait SIGCONT after reporting PID/TTY/.. but before executing the program\n" "\t-p\t\t define pts_name to attach process's I/O instead of opening a new one\n" "\t--readenv\t read environment to start process in from a file\n" "\t--env\t\t pass (additional) environment variable to the process\n" "\t--dir\t\t change working directory for starting process\n" "\t--redirect-error redirect stderror to stdout for starting process (makes sense if --no-pty only)\n" "\t--report\t record process' and exit status information into specified file\n\n" "usage: %s --dumpenv env_file\n" "\t--dumpenv\t dump environment to a file\n"
, progname, progname); exit(-1);
}
// Set SIGCONT handler for both parent and child // This is to avoid a race condition
signal(SIGCONT, sigcont);
if (params.redirect_error) {
close(STDERR_FILENO);
dup2(STDOUT_FILENO, STDERR_FILENO);
}
if (params.nopty == 0) { if (params.pty != NULL) {
pid = pty_fork1(params.pty);
} else {
pid = pty_fork(&allocated_pty_fd);
}
} else {
pid = fork(); // We call setsid for a child to make it a session leader - // this allows us later send signals to the whole session // But we don't want to do this in a single case - when --no-pty is // used but we do have terminal (because in this case the connection // with existent terminal will be lost and it will not be a controlling // terminal for the process anymore. if (!isatty(STDOUT_FILENO)) {
setsid();
}
}
if (pid < 0) {
err_sys("fork error");
}
if (pid == 0) { /* child */
/* *getanameofaterminalwehave
*/ if (isatty(STDOUT_FILENO)) {
params.pty = ttyname(STDOUT_FILENO);
}
// MAGIC variable to be used to find all children of this process char magic[20];
snprintf(magic, 20, "NBMAGIC=%ld", (long) getppid());
printf("PID=%d\n", getpid());
printf("TTY=%s\n", params.pty == NULL ? "null" : params.pty);
printf("PSID=%d\n", getsid(0)); if (params.reportfile != NULL) {
printf("REPORT=%s.%ld\n", params.reportfile, (long) getppid());
}
printf("%s\n", magic);
printf("\n"); // empty line means that we printed everything we needed
fflush(stdout);
// Just before doing execvp - notify the parent process so that // it can take a start time snapshot // Parent doesn't explicitly wait for this signal, but guarantees that // it is not blocked
kill(getppid(), SIGCONT);
if (params.wdir != NULL) { if (chdir(params.wdir) == -1) {
err_sys2(errno == ENOENT ? 127 : 1, "failed to change directory: %s", params.wdir);
}
}
// setvbuf is not retained across an exec, (as buffering is a property // of a FILE, not fd - so need to do un-buffering in the execd process. // Use LD_PRELOAD for this.. // This is controlled by java code for now, at least
if (execvp(argv[0], argv) < 0) {
err_sys2(errno == ENOENT ? 127 : 1, "failed to start %s", argv[0]);
}
/* *Ifwehaveanewlyallocatedterminal-startaloopthatre-directs *process'sI/Otoaterminal.
*/ if (allocated_pty_fd > 0) { // At least on Windows, when gdb is started through this pty process // and calling process is killed (i.e. stdin gets broken) // and even when we close master_fd, gdb continues to work... // ??? will kill the process (gdb) in this case... int loop_result = loop(allocated_pty_fd); /* copies stdin -> ptym, ptym -> stdout */
if (loop_result != 0) { int attempt = 2; while (attempt-- >= 0 && kill(pid, 0) == 0) {
kill(pid, SIGTERM);
sleep(1);
}
/* *Thereisaracehere!! *Ibetitcouldbethatgot_sigchldis0,butsignalisalreadysend *??WhatiswesendSIGKILLtothechild(thecodeabove)?-seemsthatin *thiscasesignalissentaswell... * *WillhungonaSIGCHLDifsignalwasnotalreadyreceivedonly
*/ while (!got_sigchld) {
sigset_t sigset;
sigfillset(&sigset);
sigdelset(&sigset, SIGCHLD); // Do not block SIGCONT as this is a way for child to notify the parent // about user process starting moment
sigdelset(&sigset, SIGCONT);
sigsuspend(&sigset);
}
//prusage_t usage; //psinfo_t psinfo;
if (params.reportfile != NULL) { // int pfd; // char fname[PATH_MAX]; // int r = getrusage(RUSAGE_CHILDREN, &rusage); // printf("r==%d\n", r);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.