static int exec_file(pam_handle_t *pamh, char **argv, const char *logfile) { pid_t pid, rc; int p[2]; char buf[1024]; long ttl; time_t start; int i, status, intr; fd_set rd; struct timeval tv; size_t total = 0; if (pipe(p)) { _pam_log(LOG_ERR, "pipe: %s", strerror(errno)); return PAM_SYSTEM_ERR; } pid = fork(); if (pid == -1) { close(p[0]); close(p[1]); _pam_log(LOG_ERR, "fork: %s", strerror(errno)); return PAM_SYSTEM_ERR; } if (pid == 0) { /* child */ if (dup2(p[1], 1) == -1) { _pam_log(LOG_ERR, "dup2: %s", strerror(errno)); _exit(127); } for (i = sysconf(_SC_OPEN_MAX); i >= 0; i--) { if (i != 1) close(i); } open("/dev/null", O_RDONLY); if (logfile) { if (open(logfile, O_CREAT|O_APPEND|O_WRONLY, 0644) == -1) { _pam_log(LOG_ERR, "open(%s): %s", logfile, strerror(errno)); _exit(127); } } else dup2(1, 2); execv(argv[0], argv); _exit(127); } /* master */ close(p[1]); start = time(NULL); intr = 0; rc = 0; status = 0; for (i = 0; total < max_output_size;) { FD_ZERO(&rd); FD_SET(p[0], &rd); if (intr) { rc = waitpid(pid, &status, WNOHANG); if (rc == pid) break; if (rc == (pid_t)-1) { _pam_log(LOG_ERR, "waitpid: %s", strerror(errno)); break; } intr = 0; } ttl = timeout_option - (time(NULL) - start); if (ttl <= 0) { _pam_log(LOG_ERR, "timed out reading from %s", argv[0]); break; } tv.tv_sec = ttl; tv.tv_usec = 0; rc = select(p[0] + 1, &rd, NULL, NULL, &tv); if (rc < 0) { if (errno == EINTR || errno == EAGAIN) { intr = 1; continue; } _pam_log(LOG_ERR, "select: %s", strerror(errno)); } if (i == sizeof(buf) - 1) { char *p; buf[i] = 0; p = strrchr(buf, '\n'); if (p) *p++ = 0; pam_info(pamh, "%s", buf); if (p && *p) { i = strlen(p); memmove(buf, p, i); } } if (FD_ISSET(p[0], &rd)) { char c; rc = read(p[0], &c, 1); if (rc == 1) { buf[i++] = c; total++; } else if (rc == 0 || errno == EINTR || errno == EAGAIN) { intr = 1; continue; } else { _pam_log(LOG_ERR, "read: %s", strerror(errno)); break; } } } if (i) { buf[i] = 0; pam_info(pamh, "%s", buf); } close(p[0]); if (rc != pid) { _pam_log(LOG_NOTICE, "killing %s (pid %lu)", argv[0], (unsigned long) pid); kill(pid, SIGKILL); while ((rc = waitpid(pid, &status, 0)) == -1 && errno == EINTR); if (rc == (pid_t)-1) { _pam_log(LOG_ERR, "waitpid: %s", strerror(errno)); return PAM_SYSTEM_ERR; } } else if (WIFEXITED(status)) { status = WEXITSTATUS(status); if (status) { _pam_log(LOG_ERR, "%s exited with status %d", argv[0], status); return PAM_SYSTEM_ERR; } } else if (WIFSIGNALED(status)) { status = WTERMSIG(status); _pam_log(LOG_ERR, "%s got signal %d", argv[0], status); return PAM_SYSTEM_ERR; } else if (status) { _pam_log(LOG_ERR, "%s failed: unknown status 0x%x", argv[0], status); return PAM_SYSTEM_ERR; } return PAM_SUCCESS; }
/* My goal is to launch a CCN transfert and verify success or failure and calculate the time taken */ int main (int argc, char **argv) { struct timeval startTime; gettimeofday (&startTime, 0); pid_t fils = fork (); if ( -1 == fils ) { fprintf (stderr,"fork failed !\n"); exit (1); } if (fils) { // I am the father int status = 0; pid_t ret = waitpid (fils, &status, 0); struct timeval endTime; gettimeofday (&endTime, 0); if ( ret < 0 ) { printf ("waitpid FAILURE\n"); exit (3); } if (ret == fils) { if (WIFEXITED (status)) { printf ("SUCCESS Exit Code %d ,Duration %ld\n", WEXITSTATUS(status), duration (&startTime, &endTime) ); if ( WEXITSTATUS(status) ) { FILE *f = fopen ("/var/log/FAILURE.TXT", "w+"); fprintf (f, "Failure PID %d, exit %d, duration %ld\n", fils, WEXITSTATUS(status), duration (&startTime, &endTime)); fclose (f); } else { FILE *f = fopen ("/var/log/SUCCESS.TXT", "w+"); fprintf (f, "%ld\n", duration (&startTime, &endTime)); fclose (f); } exit (WEXITSTATUS(status)); } if (WIFSIGNALED (status)) { printf ("SIGNALED : %d \n", WTERMSIG(status)); exit (5); } } else { printf ("waitpid FAILURE\n"); exit (4); } exit (ret); } else { int ret = execlp ("ccncatchunks2", "ccncatchunks2", "-d", "-a", "ccnx:/DATAFILE", NULL); printf ("exec return %d errno %d\n",ret , errno); exit (2); } exit (0); }
RexxObjectPtr RexxEntry systemCommandHandler(RexxExitContext *context, RexxStringObject address, RexxStringObject command) { const char *cmd = context->StringData(command); const char *envName = context->StringData(address); RexxObjectPtr rc = NULLOBJECT; /* check for redirection symbols, ignore them when enclosed in double quotes. escaped quotes are ignored. */ bool noDirectInvoc = false; bool inQuotes = false; bool escape = false; size_t i; for (i = 0; i<strlen(cmd); i++) { if (escape) { escape = false; } else if (cmd[i] == '\\') { escape = true; } else if (cmd[i] == '"') { inQuotes = !inQuotes; } else { /* if we're in the unquoted part and the current character is one of */ /* the redirection characters or the & for multiple commands then we */ /* will no longer try to invoke the command directly */ if (!inQuotes && (strchr("<>|&", cmd[i]) != NULL)) { noDirectInvoc = true; break; } } } if (!noDirectInvoc) { /* execute 'cd' in the same process */ size_t commandLen = strlen(cmd); if (strcmp(cmd, "cd") == 0) { if (sys_process_cd(context, cmd, rc)) { return rc; } } else if (commandLen >= 3) { char tmp[16]; strncpy(tmp, cmd, 3); tmp[3] = '\0'; if (strcmp("cd ",tmp) == 0) { if (sys_process_cd(context, cmd, rc)) { return rc; } } strncpy(tmp, cmd, 4); tmp[4] = '\0'; if (strcmp("set ",tmp) == 0) { if (sys_process_export(context, cmd, rc, SET_FLAG)) /*unset works fine for me*/ { return rc; } } strncpy(tmp, cmd, 6); tmp[6] = '\0'; if (Utilities::strCaselessCompare("unset ", tmp) == 0) { if (sys_process_export(context, cmd, rc, UNSET_FLAG)) { return rc; } } strncpy(tmp, cmd, 7); tmp[7] = '\0'; if (Utilities::strCaselessCompare("export ", tmp) == 0) { if (sys_process_export(context, cmd, rc, EXPORT_FLAG)) { return rc; } } } } /****************************************************************************/ /* Invoke the system command handler to execute the command */ /****************************************************************************/ // if this is the null string, then use the default address environment // for the platform if (strlen(envName) == 0) { envName = SYSINITIALADDRESS; } int errCode = 0; #ifdef LINUX if (Utilities::strCaselessCompare("bash", envName) == 0) { errCode = system( cmd ); if ( errCode >= 256 ) { errCode = errCode / 256; } } else #endif { int pid = fork(); int status; if (pid != 0) /* spawn a child process to run the */ { waitpid ( pid, &status, 0); /* command and wait for it to finish */ if (WIFEXITED(status)) /* If cmd process ended normal */ { /* Give 'em the exit code */ errCode = WEXITSTATUS(status); } else /* Else process died ugly, so */ { errCode = -(WTERMSIG(status)); if (errCode == 1) /* If process was stopped */ { errCode = -1; /* Give 'em a -1. */ } } } else { /* run the command in the child */ if (Utilities::strCaselessCompare("sh", envName) == 0) { #ifdef ANDROID execl("/system/bin/sh", "sh", "-c", cmd, NULL); #else execl("/bin/sh", "sh", "-c", cmd, NULL); #endif } else if (Utilities::strCaselessCompare("ksh", envName) == 0) { execl("/bin/ksh", "ksh", "-c", cmd, NULL); } else if (Utilities::strCaselessCompare("bsh", envName) == 0) { execl("/bin/bsh", "bsh", "-c", cmd, NULL); } else if (Utilities::strCaselessCompare("csh", envName) == 0) { execl("/bin/csh", "csh", "-c", cmd, NULL); } else if (Utilities::strCaselessCompare("bash", envName) == 0) { execl("/bin/bash", "bash", "-c", cmd, NULL); } else if (Utilities::strCaselessCompare("cmd", envName) == 0) { char * args[MAX_COMMAND_ARGS+1]; /* Array for argument parsing */ if (!scan_cmd(cmd, args)) /* Parse cmd into arguments */ { exit(1); } execvp(args[0], args); /* Invoke command directly */ exit(1); /* we couldn't run the */ } else { execl("/bin/sh", "sh", "-c", cmd, NULL); } } } // unknown command code? if (errCode == UNKNOWN_COMMAND) { // failure condition context->RaiseCondition("FAILURE", context->String(cmd), NULL, context->WholeNumberToObject(errCode)); } else if (errCode != 0) { // non-zero is an error condition context->RaiseCondition("ERROR", context->String(cmd), NULL, context->WholeNumberToObject(errCode)); } return context->False(); // zero return code }
int runLINK() { #if _WIN32 if (global.params.is64bit) { OutBuffer cmdbuf; cmdbuf.writestring("/NOLOGO "); for (size_t i = 0; i < global.params.objfiles->dim; i++) { if (i) cmdbuf.writeByte(' '); char *p = (*global.params.objfiles)[i]; char *basename = FileName::removeExt(FileName::name(p)); char *ext = FileName::ext(p); if (ext && !strchr(basename, '.')) // Write name sans extension (but not if a double extension) writeFilename(&cmdbuf, p, ext - p - 1); else writeFilename(&cmdbuf, p); mem.free(basename); } if (global.params.resfile) { cmdbuf.writeByte(' '); writeFilename(&cmdbuf, global.params.resfile); } cmdbuf.writeByte(' '); if (global.params.exefile) { cmdbuf.writestring("/OUT:"); writeFilename(&cmdbuf, global.params.exefile); } else { /* Generate exe file name from first obj name. * No need to add it to cmdbuf because the linker will default to it. */ char *n = (*global.params.objfiles)[0]; n = FileName::name(n); FileName *fn = FileName::forceExt(n, "exe"); global.params.exefile = fn->toChars(); } // Make sure path to exe file exists { char *p = FileName::path(global.params.exefile); FileName::ensurePathExists(p); mem.free(p); } cmdbuf.writeByte(' '); if (global.params.mapfile) { cmdbuf.writestring("/MAP:"); writeFilename(&cmdbuf, global.params.mapfile); } else if (global.params.map) { FileName *fn = FileName::forceExt(global.params.exefile, "map"); char *path = FileName::path(global.params.exefile); char *p; if (path[0] == '\0') p = FileName::combine(global.params.objdir, fn->toChars()); else p = fn->toChars(); cmdbuf.writestring("/MAP:"); writeFilename(&cmdbuf, p); } for (size_t i = 0; i < global.params.libfiles->dim; i++) { cmdbuf.writeByte(' '); cmdbuf.writestring("/DEFAULTLIB:"); writeFilename(&cmdbuf, (*global.params.libfiles)[i]); } if (global.params.deffile) { cmdbuf.writeByte(' '); cmdbuf.writestring("/DEF:"); writeFilename(&cmdbuf, global.params.deffile); } if (global.params.symdebug) { cmdbuf.writeByte(' '); cmdbuf.writestring("/DEBUG"); } if (global.params.dll) { cmdbuf.writeByte(' '); cmdbuf.writestring("/DLL"); } cmdbuf.writestring(" /MERGE:.minfobg=.minfodt /MERGE:.minfoen=.minfodt"); cmdbuf.writestring(" /MERGE:._deh_bg=._deh_eh /MERGE:._deh_en=._deh_eh"); for (size_t i = 0; i < global.params.linkswitches->dim; i++) { cmdbuf.writeByte(' '); cmdbuf.writestring((*global.params.linkswitches)[i]); } /* Append the path to the VC lib files, and then the SDK lib files */ const char *vcinstalldir = getenv("VCINSTALLDIR"); if (vcinstalldir) { cmdbuf.writestring(" \"/LIBPATH:"); cmdbuf.writestring(vcinstalldir); cmdbuf.writestring("lib\\amd64\""); } const char *windowssdkdir = getenv("WindowsSdkDir"); if (windowssdkdir) { cmdbuf.writestring(" \"/LIBPATH:"); cmdbuf.writestring(windowssdkdir); cmdbuf.writestring("lib\\x64\""); } char *p = cmdbuf.toChars(); FileName *lnkfilename = NULL; size_t plen = strlen(p); if (plen > 7000) { lnkfilename = FileName::forceExt(global.params.exefile, "lnk"); File flnk(lnkfilename); flnk.setbuffer(p, plen); flnk.ref = 1; if (flnk.write()) error(0, "error writing file %s", lnkfilename); if (lnkfilename->len() < plen) sprintf(p, "@%s", lnkfilename->toChars()); } char *linkcmd = getenv("LINKCMD64"); if (!linkcmd) { if (vcinstalldir) { OutBuffer linkcmdbuf; linkcmdbuf.writestring(vcinstalldir); linkcmdbuf.writestring("bin\\amd64\\link"); linkcmd = linkcmdbuf.toChars(); linkcmdbuf.extractData(); } else linkcmd = "link"; } int status = executecmd(linkcmd, p, 1); if (lnkfilename) { remove(lnkfilename->toChars()); delete lnkfilename; } return status; } else { OutBuffer cmdbuf; global.params.libfiles->push("user32"); global.params.libfiles->push("kernel32"); for (size_t i = 0; i < global.params.objfiles->dim; i++) { if (i) cmdbuf.writeByte('+'); char *p = (*global.params.objfiles)[i]; char *basename = FileName::removeExt(FileName::name(p)); char *ext = FileName::ext(p); if (ext && !strchr(basename, '.')) // Write name sans extension (but not if a double extension) writeFilename(&cmdbuf, p, ext - p - 1); else writeFilename(&cmdbuf, p); mem.free(basename); } cmdbuf.writeByte(','); if (global.params.exefile) writeFilename(&cmdbuf, global.params.exefile); else { /* Generate exe file name from first obj name. * No need to add it to cmdbuf because the linker will default to it. */ char *n = (*global.params.objfiles)[0]; n = FileName::name(n); FileName *fn = FileName::forceExt(n, "exe"); global.params.exefile = fn->toChars(); } // Make sure path to exe file exists { char *p = FileName::path(global.params.exefile); FileName::ensurePathExists(p); mem.free(p); } cmdbuf.writeByte(','); if (global.params.mapfile) writeFilename(&cmdbuf, global.params.mapfile); else if (global.params.map) { FileName *fn = FileName::forceExt(global.params.exefile, "map"); char *path = FileName::path(global.params.exefile); char *p; if (path[0] == '\0') p = FileName::combine(global.params.objdir, fn->toChars()); else p = fn->toChars(); writeFilename(&cmdbuf, p); } else cmdbuf.writestring("nul"); cmdbuf.writeByte(','); for (size_t i = 0; i < global.params.libfiles->dim; i++) { if (i) cmdbuf.writeByte('+'); writeFilename(&cmdbuf, (*global.params.libfiles)[i]); } if (global.params.deffile) { cmdbuf.writeByte(','); writeFilename(&cmdbuf, global.params.deffile); } /* Eliminate unnecessary trailing commas */ while (1) { size_t i = cmdbuf.offset; if (!i || cmdbuf.data[i - 1] != ',') break; cmdbuf.offset--; } if (global.params.resfile) { cmdbuf.writestring("/RC:"); writeFilename(&cmdbuf, global.params.resfile); } if (global.params.map || global.params.mapfile) cmdbuf.writestring("/m"); #if 0 if (debuginfo) cmdbuf.writestring("/li"); if (codeview) { cmdbuf.writestring("/co"); if (codeview3) cmdbuf.writestring(":3"); } #else if (global.params.symdebug) cmdbuf.writestring("/co"); #endif cmdbuf.writestring("/noi"); for (size_t i = 0; i < global.params.linkswitches->dim; i++) { cmdbuf.writestring((*global.params.linkswitches)[i]); } cmdbuf.writeByte(';'); char *p = cmdbuf.toChars(); FileName *lnkfilename = NULL; size_t plen = strlen(p); if (plen > 7000) { lnkfilename = FileName::forceExt(global.params.exefile, "lnk"); File flnk(lnkfilename); flnk.setbuffer(p, plen); flnk.ref = 1; if (flnk.write()) error(0, "error writing file %s", lnkfilename); if (lnkfilename->len() < plen) sprintf(p, "@%s", lnkfilename->toChars()); } char *linkcmd = getenv("LINKCMD"); if (!linkcmd) linkcmd = "link"; int status = executecmd(linkcmd, p, 1); if (lnkfilename) { remove(lnkfilename->toChars()); delete lnkfilename; } return status; } #elif linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun pid_t childpid; int status; // Build argv[] Strings argv; const char *cc = getenv("CC"); if (!cc) cc = "gcc"; argv.push((char *)cc); argv.insert(1, global.params.objfiles); #if __APPLE__ // If we are on Mac OS X and linking a dynamic library, // add the "-dynamiclib" flag if (global.params.dll) argv.push((char *) "-dynamiclib"); #elif linux || __FreeBSD__ || __OpenBSD__ || __sun if (global.params.dll) argv.push((char *) "-shared"); #endif // None of that a.out stuff. Use explicit exe file name, or // generate one from name of first source file. argv.push((char *)"-o"); if (global.params.exefile) { if (global.params.dll) global.params.exefile = FileName::forceExt(global.params.exefile, global.dll_ext)->toChars(); argv.push(global.params.exefile); } else { // Generate exe file name from first obj name char *n = (*global.params.objfiles)[0]; char *e; char *ex; n = FileName::name(n); e = FileName::ext(n); if (e) { e--; // back up over '.' ex = (char *)mem.malloc(e - n + 1); memcpy(ex, n, e - n); ex[e - n] = 0; // If generating dll then force dll extension if (global.params.dll) ex = FileName::forceExt(ex, global.dll_ext)->toChars(); } else ex = (char *)"a.out"; // no extension, so give up argv.push(ex); global.params.exefile = ex; } // Make sure path to exe file exists { char *p = FileName::path(global.params.exefile); FileName::ensurePathExists(p); mem.free(p); } if (global.params.symdebug) argv.push((char *)"-g"); if (global.params.is64bit) argv.push((char *)"-m64"); else argv.push((char *)"-m32"); if (global.params.map || global.params.mapfile) { argv.push((char *)"-Xlinker"); #if __APPLE__ argv.push((char *)"-map"); #else argv.push((char *)"-Map"); #endif if (!global.params.mapfile) { FileName *fn = FileName::forceExt(global.params.exefile, "map"); char *path = FileName::path(global.params.exefile); char *p; if (path[0] == '\0') p = FileName::combine(global.params.objdir, fn->toChars()); else p = fn->toChars(); global.params.mapfile = p; } argv.push((char *)"-Xlinker"); argv.push(global.params.mapfile); } if (0 && global.params.exefile) { /* This switch enables what is known as 'smart linking' * in the Windows world, where unreferenced sections * are removed from the executable. It eliminates unreferenced * functions, essentially making a 'library' out of a module. * Although it is documented to work with ld version 2.13, * in practice it does not, but just seems to be ignored. * Thomas Kuehne has verified that it works with ld 2.16.1. * BUG: disabled because it causes exception handling to fail * because EH sections are "unreferenced" and elided */ argv.push((char *)"-Xlinker"); argv.push((char *)"--gc-sections"); } for (size_t i = 0; i < global.params.linkswitches->dim; i++) { char *p = (*global.params.linkswitches)[i]; if (!p || !p[0] || !(p[0] == '-' && (p[1] == 'l' || p[1] == 'L'))) // Don't need -Xlinker if switch starts with -l or -L. // Eliding -Xlinker is significant for -L since it allows our paths // to take precedence over gcc defaults. argv.push((char *)"-Xlinker"); argv.push(p); } /* Add each library, prefixing it with "-l". * The order of libraries passed is: * 1. any libraries passed with -L command line switch * 2. libraries specified on the command line * 3. libraries specified by pragma(lib), which were appended * to global.params.libfiles. * 4. standard libraries. */ for (size_t i = 0; i < global.params.libfiles->dim; i++) { char *p = (*global.params.libfiles)[i]; size_t plen = strlen(p); if (plen > 2 && p[plen - 2] == '.' && p[plen -1] == 'a') argv.push(p); else { char *s = (char *)mem.malloc(plen + 3); s[0] = '-'; s[1] = 'l'; memcpy(s + 2, p, plen + 1); argv.push(s); } } /* Standard libraries must go after user specified libraries * passed with -l. */ const char *libname = (global.params.symdebug) ? global.params.debuglibname : global.params.defaultlibname; size_t slen = strlen(libname); if (slen) { char *buf = (char *)malloc(2 + slen + 1); strcpy(buf, "-l"); strcpy(buf + 2, libname); argv.push(buf); // turns into /usr/lib/libphobos2.a } #ifdef __sun argv.push((char *)"-mt"); #endif // argv.push((void *)"-ldruntime"); argv.push((char *)"-lpthread"); argv.push((char *)"-lm"); #if linux && DMDV2 // Changes in ld for Ubuntu 11.10 require this to appear after phobos2 argv.push((char *)"-lrt"); #endif if (!global.params.quiet || global.params.verbose) { // Print it for (size_t i = 0; i < argv.dim; i++) printf("%s ", argv[i]); printf("\n"); fflush(stdout); } argv.push(NULL); // set up pipes int fds[2]; if (pipe(fds) == -1) { perror("Unable to create pipe to linker"); return -1; } childpid = fork(); if (childpid == 0) { // pipe linker stderr to fds[0] dup2(fds[1], STDERR_FILENO); close(fds[0]); execvp(argv[0], argv.tdata()); perror(argv[0]); // failed to execute return -1; } else if (childpid == -1) { perror("Unable to fork"); return -1; } close(fds[1]); const int nme = findNoMainError(fds[0]); waitpid(childpid, &status, 0); if (WIFEXITED(status)) { status = WEXITSTATUS(status); if (status) { if (nme == -1) { perror("Error with the linker pipe"); return -1; } else { printf("--- errorlevel %d\n", status); if (nme == 1) error(0, "no main function specified"); } } } else if (WIFSIGNALED(status)) { printf("--- killed by signal %d\n", WTERMSIG(status)); status = 1; } return status; #else printf ("Linking is not yet supported for this version of DMD.\n"); return -1; #endif }
/* Test each page. */ static bool TestPage(const char *pagelabel, uintptr_t pageaddr, int should_succeed) { const char *oplabel; uintptr_t opaddr; bool failed = false; for (unsigned int test = 0; test < 3; test++) { switch (test) { // The execute test must be done before the write test, because the // write test will clobber memory at the target address. case 0: oplabel = "reading"; opaddr = pageaddr + PAGESIZE/2 - 1; break; case 1: oplabel = "executing"; opaddr = pageaddr + PAGESIZE/2; break; case 2: oplabel = "writing"; opaddr = pageaddr + PAGESIZE/2 - 1; break; default: abort(); } #ifdef _WIN32 BOOL badptr; switch (test) { case 0: badptr = IsBadReadPtr((const void*)opaddr, 1); break; case 1: badptr = IsBadExecPtr(opaddr); break; case 2: badptr = IsBadWritePtr((void*)opaddr, 1); break; default: abort(); } if (badptr) { if (should_succeed) { printf("TEST-UNEXPECTED-FAIL | %s %s\n", oplabel, pagelabel); failed = true; } else { printf("TEST-PASS | %s %s\n", oplabel, pagelabel); } } else { // if control reaches this point the probe succeeded if (should_succeed) { printf("TEST-PASS | %s %s\n", oplabel, pagelabel); } else { printf("TEST-UNEXPECTED-FAIL | %s %s\n", oplabel, pagelabel); failed = true; } } #elif defined(__OS2__) XCPT xcpt; volatile int code = setjmp(xcpt.jmpbuf); if (!code) { xcpt.regrec.prev_structure = 0; xcpt.regrec.ExceptionHandler = ExceptionHandler; DosSetExceptionHandler(&xcpt.regrec); unsigned char scratch; switch (test) { case 0: scratch = *(volatile unsigned char *)opaddr; break; case 1: ((void (*)())opaddr)(); break; case 2: *(volatile unsigned char *)opaddr = 0; break; default: abort(); } } if (code) { if (should_succeed) { printf("TEST-UNEXPECTED-FAIL | %s %s | exception code %x\n", oplabel, pagelabel, code); failed = true; } else { printf("TEST-PASS | %s %s | exception code %x\n", oplabel, pagelabel, code); } } else { if (should_succeed) { printf("TEST-PASS | %s %s\n", oplabel, pagelabel); } else { printf("TEST-UNEXPECTED-FAIL | %s %s\n", oplabel, pagelabel); failed = true; } DosUnsetExceptionHandler(&xcpt.regrec); } #else pid_t pid = fork(); if (pid == -1) { printf("ERROR | %s %s | fork=%s\n", oplabel, pagelabel, LastErrMsg()); exit(2); } else if (pid == 0) { volatile unsigned char scratch; switch (test) { case 0: scratch = *(volatile unsigned char *)opaddr; break; case 1: JumpTo(opaddr); break; case 2: *(volatile unsigned char *)opaddr = 0; break; default: abort(); } (void)scratch; _exit(0); } else { int status; if (waitpid(pid, &status, 0) != pid) { printf("ERROR | %s %s | wait=%s\n", oplabel, pagelabel, LastErrMsg()); exit(2); } if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { if (should_succeed) { printf("TEST-PASS | %s %s\n", oplabel, pagelabel); } else { printf("TEST-UNEXPECTED-FAIL | %s %s | unexpected successful exit\n", oplabel, pagelabel); failed = true; } } else if (WIFEXITED(status)) { printf("ERROR | %s %s | unexpected exit code %d\n", oplabel, pagelabel, WEXITSTATUS(status)); exit(2); } else if (WIFSIGNALED(status)) { if (should_succeed) { printf("TEST-UNEXPECTED-FAIL | %s %s | unexpected signal %d\n", oplabel, pagelabel, WTERMSIG(status)); failed = true; } else { printf("TEST-PASS | %s %s | signal %d (as expected)\n", oplabel, pagelabel, WTERMSIG(status)); } } else { printf("ERROR | %s %s | unexpected exit status %d\n", oplabel, pagelabel, status); exit(2); } } #endif } return failed; }
int Mod_fw_replace(FW_handle_T handle, const char *set_name, List_T cidrs, short af) { struct fw_handle *fwh = handle->fwh; int fd, nadded = 0, child = -1, status; char *cidr, *fd_path = NULL, *pfctl_path = PFCTL_PATH; char *table = (char *) set_name; static FILE *pf = NULL; struct List_entry *entry; struct sigaction act, oldact; char *argv[11] = { "pfctl", "-p", PFDEV_PATH, "-q", "-t", table, "-T", "replace", "-f", "-", NULL }; if(List_size(cidrs) == 0) return 0; pfctl_path = Config_get_str(handle->config, "pfctl_path", "firewall", PFCTL_PATH); if(asprintf(&fd_path, "/dev/fd/%d", fwh->pfdev) == -1) return -1; argv[2] = fd_path; memset(&act, 0, sizeof(act)); act.sa_handler = SIG_DFL; sigaction(SIGCHLD, &act, &oldact); if((pf = setup_cntl_pipe(pfctl_path, argv, &child)) == NULL) { free(fd_path); fd_path = NULL; goto err; } free(fd_path); fd_path = NULL; LIST_EACH(cidrs, entry) { if((cidr = List_entry_value(entry)) != NULL) { fprintf(pf, "%s\n", cidr); nadded++; } } fclose(pf); waitpid(child, &status, 0); if(WIFEXITED(status) && WEXITSTATUS(status) != 0) { i_warning("%s returned status %d", pfctl_path, WEXITSTATUS(status)); goto err; } else if(WIFSIGNALED(status)) { i_warning("%s died on signal %d", pfctl_path, WTERMSIG(status)); goto err; } signal(SIGCHLD, &oldact, NULL); return nadded; err: return -1; }
int main(int argc, char **argv) { pid_t pid_fils, pid_ret; int statut_fils; pid=getpid(); ppid=getppid(); printmsg("Creation depuis le shell"); /* 1. Fonction en cas de terminaison du processus. NB : elle sera heritee par le processus fils. */ atexit(adieu); /* 2. Creation du processus fils */ switch ( pid_fils = fork() ) { case (pid_t)-1: /* Echec du fork */ perror("main/fork"); exit(EXIT_FAILURE); case (pid_t)0: /* DEBUT PROCESSUS FILS */ strcpy(str_identp, "fils"); strcpy(str_decale, " "); pid=getpid(); ppid=getppid(); printmsg("creation par processus pere"); for(int i=1; i <= DURATION; i+=2) { printmsg("toujours vivant"); sleep(2); } exit(EXIT_SUCCESS); /* FIN DU PROCESSUS FILS */ default: /* Suite du processus pere */ sprintf(str_buffer, "creation d'un processus fils de pid %d", pid_fils); printmsg(str_buffer); } /* 3. Attente non bloquante du processus fils */ switch ( pid_ret = waitpid(pid_fils, &statut_fils, WNOHANG) ) { case (pid_t)-1: /* Echec du waitpid */ perror("main/waitpid WNOHANG"); exit(EXIT_FAILURE); case (pid_t)0: /* Le processus fils attendu n'est pas termine */ printmsg("attente fils non termine"); /* 4. Attente bloquante du processus fils */ switch( pid_ret =waitpid(pid_fils, &statut_fils, WUNTRACED) ) { case (pid_t)-1: /* Echec du waitpid() */ perror("main/waitpid WUNTRACED -1"); exit(EXIT_FAILURE); case (pid_t)0: /* Ne devrait pas se produire */ perror("main/waitpid WUNTRACED 0"); exit(EXIT_FAILURE); default: /* Le processus fils attendu est termine */ sprintf(str_buffer, "fin du fils de pid %d (pid demande = %d)", pid_ret, pid_fils); printmsg(str_buffer); } break; default: /* Le processus fils attendu est termine. */ sprintf(str_buffer, "fin du fils de pid %d (pid demande = %d)", pid_ret, pid_fils); printmsg(str_buffer); } /* 5. Examen du code de retour du processus fils */ if( WIFEXITED(statut_fils) != 0 ) { sprintf(str_buffer, "code de retour du fils %d = %d", (int)pid_fils, WEXITSTATUS(statut_fils)); printmsg(str_buffer); } if( WIFSIGNALED(statut_fils) != 0 ) { sprintf(str_buffer, "fin du fils %d due au signal %d non intercepte", (int)pid_fils, WTERMSIG(statut_fils)); printmsg(str_buffer); } if( WIFSTOPPED(statut_fils) != 0 ) { sprintf(str_buffer, "processsus fils %d stoppe par signal %d", (int)pid_fils, WSTOPSIG(statut_fils)); printmsg(str_buffer); } return EXIT_SUCCESS; }
int main(int argc, char *argv[]) { int secs, stat; pid_t pid; unsigned int revs = 0; struct sigaction zig; if (argc < 3) { printf("Usage: %s time_in_sec command [args]\n", argv[0]); exit(1); } tty_fp = fdopen(3, "w+"); if (tty_fp == NULL) { tty_fp = fopen("/dev/tty", "w+"); if (tty_fp == NULL) { perror("stdout"); exit(2); } } progname = rindex(argv[2], '/'); if (progname == NULL) { progname = argv[2]; } else { progname++; } /* Set up signals */ memset(&zig, 0x00, sizeof(zig)); zig.sa_handler = alarm_func; sigaction(SIGALRM, &zig, NULL); zig.sa_handler = int_func; sigaction(SIGINT, &zig, NULL); sigaction(SIGTERM, &zig, NULL); /* set up process groups so that we can kill the * loop test and descendants easily */ secs = atoi(argv[1]); alarm(secs); while (1) { pounder_fprintf(tty_fp, "%s: %s loop #%d.\n", progname, start_msg, revs++); pid = fork(); if (pid == 0) { if (setpgrp() < 0) { perror("setpgid"); } // run the program if (argc > 3) { stat = execvp(argv[2], &argv[2]); } else { stat = execvp(argv[2], &argv[2]); } perror(argv[2]); exit(-1); } /* save the pgrp of the spawned process */ test_pgrp = pid; // wait for it to be done if (waitpid(pid, &stat, 0) != pid) { perror("waitpid"); exit(1); } // interrogate it if (WIFSIGNALED(stat)) { pounder_fprintf(tty_fp, "%s: %s on signal %d.\n", progname, fail_msg, WTERMSIG(stat)); res = 255; } else { res = WEXITSTATUS(stat); if (res == 0) { pounder_fprintf(tty_fp, "%s: %s.\n", progname, pass_msg); } else if (res < 0 || res == 255) { pounder_fprintf(tty_fp, "%s: %s with code %d.\n", progname, abort_msg, res); exit(-1); // FIXME: add test to blacklist } else { pounder_fprintf(tty_fp, "%s: %s with code %d.\n", progname, fail_msg, res); } } } }
void doit () { int err, i; int sockets[2]; const char *srcdir; char *pub_key_path, *priv_key_path; pid_t child; gnutls_global_init (); srcdir = getenv ("srcdir") ? getenv ("srcdir") : "."; for (i = 0; i < 4; i++) { if (i <= 1) key_id = NULL; /* try using the master key */ else if (i == 2) key_id = "auto"; /* test auto */ else if (i == 3) key_id = "f30fd423c143e7ba"; if (debug) { gnutls_global_set_log_level (5); gnutls_global_set_log_function (log_message); } err = socketpair (PF_UNIX, SOCK_STREAM, 0, sockets); if (err != 0) fail ("socketpair %s\n", strerror (errno)); pub_key_path = alloca (strlen (srcdir) + strlen (pub_key_file) + 2); strcpy (pub_key_path, srcdir); strcat (pub_key_path, "/"); strcat (pub_key_path, pub_key_file); priv_key_path = alloca (strlen (srcdir) + strlen (priv_key_file) + 2); strcpy (priv_key_path, srcdir); strcat (priv_key_path, "/"); strcat (priv_key_path, priv_key_file); child = fork (); if (child == -1) fail ("fork %s\n", strerror (errno)); if (child == 0) { /* Child process (client). */ gnutls_session_t session; gnutls_certificate_credentials_t cred; ssize_t sent; if (debug) printf ("client process %i\n", getpid ()); err = gnutls_init (&session, GNUTLS_CLIENT); if (err != 0) fail ("client session %d\n", err); if (i==0) /* we use the primary key which is RSA. Test the RSA ciphersuite */ gnutls_priority_set_direct (session, "NONE:+VERS-TLS1.0:+CIPHER-ALL:+MAC-ALL:+SIGN-ALL:+COMP-ALL:+RSA:+CTYPE-OPENPGP", NULL); else gnutls_priority_set_direct (session, "NONE:+VERS-TLS1.0:+CIPHER-ALL:+MAC-ALL:+SIGN-ALL:+COMP-ALL:+DHE-DSS:+DHE-RSA:+CTYPE-OPENPGP", NULL); gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) (intptr_t) sockets[0]); err = gnutls_certificate_allocate_credentials (&cred); if (err != 0) fail ("client credentials %d\n", err); err = gnutls_certificate_set_openpgp_key_file2 (cred, pub_key_path, priv_key_path, key_id, GNUTLS_OPENPGP_FMT_BASE64); if (err != 0) fail ("client openpgp keys %s\n", gnutls_strerror (err)); err = gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, cred); if (err != 0) fail ("client credential_set %d\n", err); gnutls_dh_set_prime_bits (session, 1024); err = gnutls_handshake (session); if (err != 0) fail ("client handshake %s (%d) \n", gnutls_strerror (err), err); else if (debug) printf ("client handshake successful\n"); sent = gnutls_record_send (session, message, sizeof (message)); if (sent != sizeof (message)) fail ("client sent %li vs. %li\n", (long) sent, (long) sizeof (message)); err = gnutls_bye (session, GNUTLS_SHUT_RDWR); if (err != 0) fail ("client bye %d\n", err); if (debug) printf ("client done\n"); gnutls_deinit(session); gnutls_certificate_free_credentials (cred); } else { /* Parent process (server). */ gnutls_session_t session; gnutls_dh_params_t dh_params; gnutls_certificate_credentials_t cred; char greetings[sizeof (message) * 2]; ssize_t received; pid_t done; int status; const gnutls_datum_t p3 = { (char *) pkcs3, strlen (pkcs3) }; if (debug) printf ("server process %i (child %i)\n", getpid (), child); err = gnutls_init (&session, GNUTLS_SERVER); if (err != 0) fail ("server session %d\n", err); gnutls_priority_set_direct (session, "NONE:+VERS-TLS1.0:+CIPHER-ALL:+MAC-ALL:+SIGN-ALL:+COMP-ALL:+DHE-DSS:+DHE-RSA:+RSA:+CTYPE-OPENPGP", NULL); gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) (intptr_t) sockets[1]); err = gnutls_certificate_allocate_credentials (&cred); if (err != 0) fail ("server credentials %d\n", err); err = gnutls_certificate_set_openpgp_key_file2 (cred, pub_key_path, priv_key_path, key_id, GNUTLS_OPENPGP_FMT_BASE64); if (err != 0) fail ("server openpgp keys %s\n", gnutls_strerror (err)); err = gnutls_dh_params_init (&dh_params); if (err) fail ("server DH params init %d\n", err); err = gnutls_dh_params_import_pkcs3 (dh_params, &p3, GNUTLS_X509_FMT_PEM); if (err) fail ("server DH params generate %d\n", err); gnutls_certificate_set_dh_params (cred, dh_params); err = gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, cred); if (err != 0) fail ("server credential_set %d\n", err); gnutls_certificate_server_set_request (session, GNUTLS_CERT_REQUIRE); err = gnutls_handshake (session); if (err != 0) fail ("server handshake %s (%d) \n", gnutls_strerror (err), err); received = gnutls_record_recv (session, greetings, sizeof (greetings)); if (received != sizeof (message) || memcmp (greetings, message, sizeof (message))) fail ("server received %li vs. %li\n", (long) received, (long) sizeof (message)); err = gnutls_bye (session, GNUTLS_SHUT_RDWR); if (err != 0) fail ("server bye %s (%d) \n", gnutls_strerror (err), err); if (debug) printf ("server done\n"); gnutls_deinit(session); gnutls_certificate_free_credentials (cred); gnutls_dh_params_deinit (dh_params); done = wait (&status); if (done < 0) fail ("wait %s\n", strerror (errno)); if (done != child) fail ("who's that?! %d\n", done); if (WIFEXITED (status)) { if (WEXITSTATUS (status) != 0) fail ("child exited with status %d\n", WEXITSTATUS (status)); } else if (WIFSIGNALED (status)) fail ("child stopped by signal %d\n", WTERMSIG (status)); else fail ("child failed: %d\n", status); } } }
int main(int argc, char **argv) { int c; uid_t uid = -1; gid_t gid = -1; int pid; char **cmd; gid_t sgids[SUP_MAX]; int sup_cnt = 0; int status; char *p; prog = basename(argv[0]); for (p = prog; *p; p++) { if (*p == '/') { prog = p + 1; } } while ((c = getopt(argc, argv, "u:g:s:")) != -1) { switch (c) { case 'u': uid = atoi(optarg); break; case 'g': gid = atoi(optarg); break; case 's': if (sup_cnt+1 > SUP_MAX) { fprintf(stderr, "%s: too many sup groups\n", prog); exit(1); } sgids[sup_cnt++] = atoi(optarg); break; case '?': usage(); exit(1); } } /* build up the cmd */ if (optind == argc) { usage(); exit(1); } else { char **p; p = cmd = (char **)malloc(sizeof(char *) * (argc - optind + 1)); for ( ; optind < argc; optind++, p++) { *p = strdup(argv[optind]); } *p = NULL; } if (gid != -1) { if (setegid(gid) == -1) { fprintf(stderr, "%s: setegid(%d) failed: %s\n", prog, (int)gid, strerror(errno)); exit(1); } } if (sup_cnt > 0) { if (setgroups(sup_cnt, sgids) == -1) { fprintf(stderr, "%s: setgroups() failed: %s\n", prog, strerror(errno)); exit(1); } } if (uid != -1) { if (seteuid(uid) == -1) { fprintf(stderr, "%s: seteuid(%d) failed: %s\n", prog, (int)uid, strerror(errno)); exit(1); } } pid = fork(); if (pid == -1) { fprintf(stderr, "%s: fork failed: %s\n", prog, strerror(errno)); exit(1); } if (pid == 0) { execv(cmd[0], cmd); fprintf(stderr, "%s: %s\n", cmd[0], strerror(errno)); exit(errno); } wait(&status); if (WIFSIGNALED(status)) { fprintf(stderr, "%s: command terminated with signal %d\n", prog, WTERMSIG(status)); exit(1); } else if (WIFEXITED(status)) { exit(WEXITSTATUS(status)); } else { fprintf(stderr, "%s: command bizarre wait status 0x%x\n", prog, status); exit(1); } exit(0); /* NOTREACHED */ }
/* exit codes: 0 = ok, 1 = invocation error, 3 = internal error */ int main(int argc, char *argv[]) { int errNo; int chldPid; int chldStatus; int chldPipe[2]; char **env = 0; struct sockaddr_un sau; if (argc < ArgEnv) { fprintf(stderr, "This is an internal helper of Qt Creator. Do not run it manually.\n"); return 1; } sleepMsg = argv[ArgMsg]; /* Connect to the master, i.e. Creator. */ if ((qtcFd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) { perror("Cannot create creator comm socket"); doExit(3); } memset(&sau, 0, sizeof(sau)); sau.sun_family = AF_UNIX; strncpy(sau.sun_path, argv[ArgSocket], sizeof(sau.sun_path) - 1); if (connect(qtcFd, (struct sockaddr *)&sau, sizeof(sau))) { fprintf(stderr, "Cannot connect creator comm socket %s: %s\n", sau.sun_path, strerror(errno)); doExit(1); } if (*argv[ArgDir] && chdir(argv[ArgDir])) { /* Only expected error: no such file or direcotry */ sendMsg("err:chdir %d\n", errno); return 1; } if (*argv[ArgEnv]) { FILE *envFd; char *envdata, *edp; long size; int count; if (!(envFd = fopen(argv[ArgEnv], "r"))) { fprintf(stderr, "Cannot read creator env file %s: %s\n", argv[ArgEnv], strerror(errno)); doExit(1); } fseek(envFd, 0, SEEK_END); size = ftell(envFd); rewind(envFd); envdata = malloc(size); if (fread(envdata, 1, size, envFd) != (size_t)size) { perror("Failed to read env file"); doExit(1); } fclose(envFd); for (count = 0, edp = envdata; edp < envdata + size; ++count) edp += strlen(edp) + 1; env = malloc((count + 1) * sizeof(char *)); for (count = 0, edp = envdata; edp < envdata + size; ++count) { env[count] = edp; edp += strlen(edp) + 1; } env[count] = 0; } /* Create execution result notification pipe. */ if (pipe(chldPipe)) { perror("Cannot create status pipe"); doExit(3); } /* The debugged program is not supposed to inherit these handles. But we cannot * close the writing end before calling exec(). Just handle both ends the same way ... */ fcntl(chldPipe[0], F_SETFD, FD_CLOEXEC); fcntl(chldPipe[1], F_SETFD, FD_CLOEXEC); switch ((chldPid = fork())) { case -1: perror("Cannot fork child process"); doExit(3); case 0: close(qtcFd); /* Put the process into an own process group and make it the foregroud * group on this terminal, so it will receive ctrl-c events, etc. * This is the main reason for *all* this stub magic in the first place. */ /* If one of these calls fails, the world is about to end anyway, so * don't bother checking the return values. */ setpgid(0, 0); tcsetpgrp(0, getpid()); /* Get a SIGTRAP after exec() has loaded the new program. */ #ifdef __linux__ ptrace(PTRACE_TRACEME); #else ptrace(PT_TRACE_ME, 0, 0, 0); #endif if (env) environ = env; execvp(argv[ArgExe], argv + ArgExe); /* Only expected error: no such file or direcotry, i.e. executable not found */ errNo = errno; write(chldPipe[1], &errNo, sizeof(errNo)); /* Only realistic error case is SIGPIPE */ _exit(0); default: for (;;) { if (wait(&chldStatus) < 0) { perror("Cannot obtain exit status of child process"); doExit(3); } if (WIFSTOPPED(chldStatus)) { /* The child stopped. This can be only the result of ptrace(TRACE_ME). */ /* We won't need the notification pipe any more, as we know that * the exec() succeeded. */ close(chldPipe[0]); close(chldPipe[1]); chldPipe[0] = -1; /* If we are not debugging, just skip the "handover enabler". * This is suboptimal, as it makes us ignore setuid/-gid bits. */ if (!strcmp(argv[ArgAction], "debug")) { /* Stop the child after we detach from it, so we can hand it over to gdb. * If the signal delivery is not queued, things will go awry. It works on * Linux and MacOSX ... */ kill(chldPid, SIGSTOP); } #ifdef __linux__ ptrace(PTRACE_DETACH, chldPid, 0, 0); #else ptrace(PT_DETACH, chldPid, 0, 0); #endif sendMsg("pid %d\n", chldPid); } else if (WIFEXITED(chldStatus)) { /* The child exited normally. */ if (chldPipe[0] >= 0) { /* The child exited before being stopped by ptrace(). That can only * mean that the exec() failed. */ switch (read(chldPipe[0], &errNo, sizeof(errNo))) { default: /* Read of unknown length. Should never happen ... */ errno = EPROTO; case -1: /* Read failed. Should never happen, either ... */ perror("Cannot read status from child process"); doExit(3); case sizeof(errNo): /* Child telling us the errno from exec(). */ sendMsg("err:exec %d\n", errNo); return 3; } } sendMsg("exit %d\n", WEXITSTATUS(chldStatus)); doExit(0); } else { sendMsg("crash %d\n", WTERMSIG(chldStatus)); doExit(0); } } break; } }
int jl_process_term_signal(int status) { return WTERMSIG(status); }
static void runner(int local, char *path, char **args) { pid_t pid; if(show){ int i; if(wrapper) fprintf(stderr, "WRAPPER='%s' ", wrapper); fprintf(stderr, "%s ", path); for(i = 0; args[i]; i++) fprintf(stderr, "%s ", args[i]); fputc('\n', stderr); } if(noop) return; /* if this were to be vfork, all the code in case-0 would need to be done in the parent */ pid = fork(); switch(pid){ case -1: die("fork():"); case 0: { int nargs = dynarray_count(args); int i_in = 0, i_out = 0; char **argv; /* -wrapper gdb,--args */ if(wrapper){ char *p; nargs++; for(p = wrapper; *p; p++) nargs += *p == ','; } /* * path, * { args } * NULL-term */ argv = umalloc((2 + nargs) * sizeof *argv); /* wrapper */ if(wrapper){ char *p, *last; for(p = last = wrapper; *p; p++) if(*p == ','){ *p = '\0'; argv[i_out++] = last; last = p + 1; } if(last != p) argv[i_out++] = last; } argv[i_out++] = local ? actual_path("../", path) : path; while(args[i_in]) argv[i_out++] = args[i_in++]; argv[i_out++] = NULL; #ifdef DEBUG fprintf(stderr, "%s:\n", *argv); for(int i = 0; argv[i]; i++) fprintf(stderr, " [%d] = \"%s\",\n", i, argv[i]); #endif if(wrapper) local = 0; (local ? execv : execvp)(argv[0], argv); die("execv(\"%s\"):", argv[0]); } default: { int status, i; if(wait(&status) == -1) die("wait()"); if(WIFEXITED(status) && (i = WEXITSTATUS(status)) != 0){ die("%s returned %d", path, i); }else if(WIFSIGNALED(status)){ int sig = WTERMSIG(status); fprintf(stderr, "%s caught signal %d\n", path, sig); /* exit with propagating status */ exit(128 + sig); } } } }
/*- *----------------------------------------------------------------------- * CompatRunCommand -- * Execute the next command for a target. If the command returns an * error, the node's made field is set to ERROR and creation stops. * * Input: * cmdp Command to execute * gnp Node from which the command came * * Results: * 0 if the command succeeded, 1 if an error occurred. * * Side Effects: * The node's 'made' field may be set to ERROR. * *----------------------------------------------------------------------- */ int CompatRunCommand(void *cmdp, void *gnp) { char *cmdStart; /* Start of expanded command */ char *cp, *bp; Boolean silent, /* Don't print command */ doIt; /* Execute even if -n */ volatile Boolean errCheck; /* Check errors */ WAIT_T reason; /* Reason for child's death */ int status; /* Description of child's death */ pid_t cpid; /* Child actually found */ pid_t retstat; /* Result of wait */ LstNode cmdNode; /* Node where current command is located */ const char ** volatile av; /* Argument vector for thing to exec */ char ** volatile mav;/* Copy of the argument vector for freeing */ int argc; /* Number of arguments in av or 0 if not * dynamically allocated */ Boolean local; /* TRUE if command should be executed * locally */ Boolean useShell; /* TRUE if command should be executed * using a shell */ char * volatile cmd = (char *)cmdp; GNode *gn = (GNode *)gnp; silent = gn->type & OP_SILENT; errCheck = !(gn->type & OP_IGNORE); doIt = FALSE; cmdNode = Lst_Member(gn->commands, cmd); cmdStart = Var_Subst(NULL, cmd, gn, FALSE); /* * brk_string will return an argv with a NULL in av[0], thus causing * execvp to choke and die horribly. Besides, how can we execute a null * command? In any case, we warn the user that the command expanded to * nothing (is this the right thing to do?). */ if (*cmdStart == '\0') { free(cmdStart); return(0); } cmd = cmdStart; Lst_Replace(cmdNode, cmdStart); if ((gn->type & OP_SAVE_CMDS) && (gn != ENDNode)) { (void)Lst_AtEnd(ENDNode->commands, cmdStart); return(0); } if (strcmp(cmdStart, "...") == 0) { gn->type |= OP_SAVE_CMDS; return(0); } while ((*cmd == '@') || (*cmd == '-') || (*cmd == '+')) { switch (*cmd) { case '@': silent = DEBUG(LOUD) ? FALSE : TRUE; break; case '-': errCheck = FALSE; break; case '+': doIt = TRUE; if (!meta[0]) /* we came here from jobs */ Compat_Init(); break; } cmd++; } while (isspace((unsigned char)*cmd)) cmd++; /* * If we did not end up with a command, just skip it. */ if (!*cmd) return (0); #if !defined(MAKE_NATIVE) /* * In a non-native build, the host environment might be weird enough * that it's necessary to go through a shell to get the correct * behaviour. Or perhaps the shell has been replaced with something * that does extra logging, and that should not be bypassed. */ useShell = TRUE; #else /* * Search for meta characters in the command. If there are no meta * characters, there's no need to execute a shell to execute the * command. */ for (cp = cmd; !meta[(unsigned char)*cp]; cp++) { continue; } useShell = (*cp != '\0'); #endif /* * Print the command before echoing if we're not supposed to be quiet for * this one. We also print the command if -n given. */ if (!silent || NoExecute(gn)) { printf("%s\n", cmd); fflush(stdout); } /* * If we're not supposed to execute any commands, this is as far as * we go... */ if (!doIt && NoExecute(gn)) { return (0); } if (DEBUG(JOB)) fprintf(debug_file, "Execute: '%s'\n", cmd); again: if (useShell) { /* * We need to pass the command off to the shell, typically * because the command contains a "meta" character. */ static const char *shargv[5]; int shargc; shargc = 0; shargv[shargc++] = shellPath; /* * The following work for any of the builtin shell specs. */ if (errCheck && shellErrFlag) { shargv[shargc++] = shellErrFlag; } if (DEBUG(SHELL)) shargv[shargc++] = "-xc"; else shargv[shargc++] = "-c"; shargv[shargc++] = cmd; shargv[shargc++] = NULL; av = shargv; argc = 0; bp = NULL; mav = NULL; } else { /* * No meta-characters, so no need to exec a shell. Break the command * into words to form an argument vector we can execute. */ mav = brk_string(cmd, &argc, TRUE, &bp); if (mav == NULL) { useShell = 1; goto again; } av = (void *)mav; } local = TRUE; #ifdef USE_META if (useMeta) { meta_compat_start(); } #endif /* * Fork and execute the single command. If the fork fails, we abort. */ cpid = vFork(); if (cpid < 0) { Fatal("Could not fork"); } if (cpid == 0) { Var_ExportVars(); #ifdef USE_META if (useMeta) { meta_compat_child(); } #endif if (local) (void)execvp(av[0], (char *const *)UNCONST(av)); else (void)execv(av[0], (char *const *)UNCONST(av)); execError("exec", av[0]); _exit(1); } if (mav) free(mav); if (bp) free(bp); Lst_Replace(cmdNode, NULL); #ifdef USE_META if (useMeta) { meta_compat_parent(); } #endif /* * The child is off and running. Now all we can do is wait... */ while (1) { while ((retstat = wait(&reason)) != cpid) { if (retstat > 0) JobReapChild(retstat, reason, FALSE); /* not ours? */ if (retstat == -1 && errno != EINTR) { break; } } if (retstat > -1) { if (WIFSTOPPED(reason)) { status = WSTOPSIG(reason); /* stopped */ } else if (WIFEXITED(reason)) { status = WEXITSTATUS(reason); /* exited */ #if defined(USE_META) && defined(USE_FILEMON_ONCE) if (useMeta) { meta_cmd_finish(NULL); } #endif if (status != 0) { if (DEBUG(ERROR)) { fprintf(debug_file, "\n*** Failed target: %s\n*** Failed command: ", gn->name); for (cp = cmd; *cp; ) { if (isspace((unsigned char)*cp)) { fprintf(debug_file, " "); while (isspace((unsigned char)*cp)) cp++; } else { fprintf(debug_file, "%c", *cp); cp++; } } fprintf(debug_file, "\n"); } printf("*** Error code %d", status); } } else { status = WTERMSIG(reason); /* signaled */ printf("*** Signal %d", status); } if (!WIFEXITED(reason) || (status != 0)) { if (errCheck) { #ifdef USE_META if (useMeta) { meta_job_error(NULL, gn, 0, status); } #endif gn->made = ERROR; if (keepgoing) { /* * Abort the current target, but let others * continue. */ printf(" (continuing)\n"); } } else { /* * Continue executing commands for this target. * If we return 0, this will happen... */ printf(" (ignored)\n"); status = 0; } } break; } else { Fatal("error in wait: %d: %s", retstat, strerror(errno)); /*NOTREACHED*/ } } free(cmdStart); return (status); }
static int mountfs(const char *vfstype, const char *spec, const char *name, int flags, const char *options, const char *mntopts) { /* List of directories containing mount_xxx subcommands. */ static const char *edirs[] = { _PATH_SBIN, _PATH_USRSBIN, NULL }; const char *argv[100], **edir; struct statfs sf; pid_t pid; int argc, i, status; char *optbuf, execname[MAXPATHLEN + 1], mntpath[MAXPATHLEN]; #if __GNUC__ (void)&optbuf; (void)&name; #endif /* resolve the mountpoint with realpath(3) */ checkpath(name, mntpath); name = mntpath; if (mntopts == NULL) mntopts = ""; if (options == NULL) { if (*mntopts == '\0') { options = "rw"; } else { options = mntopts; mntopts = ""; } } optbuf = catopt(xstrdup(mntopts), options); if (strcmp(name, "/") == 0) flags |= MNT_UPDATE; if (flags & MNT_FORCE) optbuf = catopt(optbuf, "force"); if (flags & MNT_RDONLY) optbuf = catopt(optbuf, "ro"); /* * XXX * The mount_mfs (newfs) command uses -o to select the * optimization mode. We don't pass the default "-o rw" * for that reason. */ if (flags & MNT_UPDATE) optbuf = catopt(optbuf, "update"); argc = 0; argv[argc++] = vfstype; mangle(optbuf, &argc, argv); argv[argc++] = spec; argv[argc++] = name; argv[argc] = NULL; if (debug) { printf("exec: mount_%s", vfstype); for (i = 1; i < argc; i++) printf(" %s", argv[i]); printf("\n"); return (0); } switch (pid = fork()) { case -1: /* Error. */ warn("fork"); free(optbuf); return (1); case 0: /* Child. */ if (strcmp(vfstype, "ufs") == 0) exit(mount_ufs(argc, argv)); /* Go find an executable. */ for (edir = edirs; *edir; edir++) { snprintf(execname, sizeof(execname), "%s/mount_%s", *edir, vfstype); execv(execname, __DECONST(char * const *, argv)); } if (errno == ENOENT) { int len = 0; char *cp; for (edir = edirs; *edir; edir++) len += strlen(*edir) + 2; /* ", " */ if ((cp = malloc(len)) == NULL) errx(1, "malloc failed"); cp[0] = '\0'; for (edir = edirs; *edir; edir++) { strcat(cp, *edir); if (edir[1] != NULL) strcat(cp, ", "); } warn("exec mount_%s not found in %s", vfstype, cp); } exit(1); /* NOTREACHED */ default: /* Parent. */ free(optbuf); if (waitpid(pid, &status, 0) < 0) { warn("waitpid"); return (1); } if (WIFEXITED(status)) { if (WEXITSTATUS(status) != 0) return (WEXITSTATUS(status)); } else if (WIFSIGNALED(status)) { warnx("%s: %s", name, sys_siglist[WTERMSIG(status)]); return (1); } if (verbose) { if (statfs(name, &sf) < 0) { warn("statfs %s", name); return (1); } if (fstab_style) putfsent(&sf); else prmount(&sf); } break; } return (0); }
/* * sigchld_handler - The kernel sends a SIGCHLD to the shell whenever * a child job terminates (becomes a zombie), or stops because it * received a SIGSTOP or SIGTSTP signal. The handler reaps all * available zombie children, but doesn't wait for any other * currently running children to terminate. */ void sigchld_handler(int sig) { /* reaps all zombie and doesn't block */ pid_t reap_pid; int state = 0; /* used to determine what causes the SIGCHLD */ /* waitpid() return 0 immediately when no childs have terminated */ while (0 < (reap_pid = waitpid(-1, &state, WNOHANG))) { /* DBG(("reaped child %d", (int)reap_pid)); */ /*TODO Is it safe to call getjobpid(), deletejob(), clearjob() in the signal handler? */ if (WIFSIGNALED(state)) { struct job_t *termjob = getjobpid(jobs, reap_pid); fprintf(stdout, "hello Job [%d] (%d) terminated by signal %d\n", termjob->jid, termjob->pid, WTERMSIG(state)); } deletejob(jobs, reap_pid); clearjob(getjobpid(jobs, reap_pid)); } if (-1 == reap_pid && errno != ECHILD) unix_error("waitpid()"); /* if a job be suspended, we need to change its state here */ pid_t stp_pid; /* waitpid return 0 if there is no terminated process and stopped process */ while (0 < (stp_pid = waitpid(-1, &state, WNOHANG | WUNTRACED))) { struct job_t *stpjob = getjobpid(jobs, stp_pid); stpjob->state = ST; if (WIFSTOPPED(state)) { fprintf(stdout, "world Job [%d] (%d) stopped by signal %d\n", stpjob->jid, stpjob->pid, WSTOPSIG(state)); } } if (-1 == stp_pid && errno != ECHILD) unix_error("waitpid()"); }
static bool fuzz_prepareFileExternally(honggfuzz_t * hfuzz, fuzzer_t * fuzzer, int rnd_index) { int dstfd = open(fuzzer->fileName, O_CREAT | O_EXCL | O_RDWR, 0644); if (dstfd == -1) { PLOG_E("Couldn't create a temporary file '%s'", fuzzer->fileName); return false; } LOG_D("Created '%s' as an input file", fuzzer->fileName); if (hfuzz->inputFile) { size_t fileSz = files_readFileToBufMax(hfuzz->files[rnd_index], fuzzer->dynamicFile, hfuzz->maxFileSz); if (fileSz == 0UL) { LOG_E("Couldn't read '%s'", hfuzz->files[rnd_index]); unlink(fuzzer->fileName); return false; } if (files_writeToFd(dstfd, fuzzer->dynamicFile, fileSz) == false) { close(dstfd); unlink(fuzzer->fileName); return false; } } close(dstfd); pid_t pid = arch_fork(hfuzz); if (pid == -1) { PLOG_E("Couldn't fork"); return false; } if (!pid) { /* * child performs the external file modifications */ execl(hfuzz->externalCommand, hfuzz->externalCommand, fuzzer->fileName, NULL); PLOG_F("Couldn't execute '%s %s'", hfuzz->externalCommand, fuzzer->fileName); return false; } /* * parent waits until child is done fuzzing the input file */ int childStatus; int flags = 0; #if defined(__WNOTHREAD) flags |= __WNOTHREAD; #endif /* defined(__WNOTHREAD) */ while (wait4(pid, &childStatus, flags, NULL) != pid) ; if (WIFEXITED(childStatus)) { LOG_D("External command exited with status %d", WEXITSTATUS(childStatus)); return true; } if (WIFSIGNALED(childStatus)) { LOG_E("External command terminated with signal %d", WTERMSIG(childStatus)); return false; } LOG_F("External command terminated abnormally, status: %d", childStatus); return false; abort(); /* NOTREACHED */ }
//SIGPIPE是正常的信号,对端断开后本端协议栈在向对端传送数据时,对端会返回TCP RST,导致本端抛出SIGPIPE信号 void init_daemon(char* cmd) { int pid; char *buf = "This is a Daemon, wcdj\n"; char path[FILEPATH_MAX]; getRealPath(path); strcat(path,"/"); strcat(path,"pushserver.lock"); pid = readPidFile(path); if(pid != -1) { printf("The server is start ...\n"); } if(strcmp(cmd,"stop") == 0 && pid != -1){ closeServer(pid,0); int status; int w; do { w = waitpid(pid, &status, WUNTRACED | WCONTINUED); if (w == -1) { perror("waitpid"); exit(EXIT_FAILURE); } if (WIFEXITED(status)) { printf("exited, status=%d/n", WEXITSTATUS(status)); } else if (WIFSIGNALED(status)) { printf("killed by signal %d/n", WTERMSIG(status)); } else if (WIFSTOPPED(status)) { printf("stopped by signal %d/n", WSTOPSIG(status)); } else if (WIFCONTINUED(status)) { printf("continued/n"); } } while (!WIFEXITED(status) && !WIFSIGNALED(status)); exit(0); } else if(strcmp(cmd,"restart") == 0 && pid != -1){ int status; int w; do { w = waitpid(pid, &status, WUNTRACED | WCONTINUED); if (w == -1) { perror("waitpid"); exit(EXIT_FAILURE); } if (WIFEXITED(status)) { printf("exited, status=%d/n", WEXITSTATUS(status)); } else if (WIFSIGNALED(status)) { printf("killed by signal %d/n", WTERMSIG(status)); } else if (WIFSTOPPED(status)) { printf("stopped by signal %d/n", WSTOPSIG(status)); } else if (WIFCONTINUED(status)) { printf("continued/n"); } } while (!WIFEXITED(status) && !WIFSIGNALED(status)); }else if(pid != -1){ printf("The server is start ...\n"); exit(0); } /* 屏蔽一些有关控制终端操作的信号 * 防止在守护进程没有正常运转起来时,因控制终端受到干扰退出或挂起 */ signal(SIGINT, SIG_IGN);// 终端中断 signal(SIGHUP, SIG_IGN);// 连接挂断 signal(SIGQUIT, SIG_IGN);// 终端退出 signal(SIGPIPE, SIG_IGN);// 向无读进程的管道写数据 signal(SIGTTOU, SIG_IGN);// 后台程序尝试写操作 signal(SIGTTIN, SIG_IGN);// 后台程序尝试读操作 signal(SIGTERM, SIG_IGN);// 终止 struct rlimit rl; if (getrlimit(RLIMIT_NOFILE, &rl) < 0) printf("%s: can't get file limit", "pushserver"); int i; /* pid=fork(); if(pid>0) exit(0);//是父进程,结束父进程 else if(pid< 0) exit(1);//fork失败,退出 //是第一子进程,后台继续执行 setsid();//第一子进程成为新的会话组长和进程组长 //并与控制终端分离 pid=fork(); if(pid>0) exit(0);//是第一子进程,结束第一子进程 else if(pid< 0) exit(1);//fork失败,退出 */ if ((pid = fork()) < 0) printf("%s: can't fork", cmd); else if (pid != 0) /* parent */{ printf("tuichuzhu\n"); exit(0); } printf("jinlaile\n"); setsid(); //是第二子进程,继续 //第二子进程不再是会话组长 main_pid = getpid(); writePidFile(path); for(i=3;i< NOFILE;++i)//关闭打开的文件描述符 MAXFILE 65536 close(i); /* // [3] set current path char szPath[1024]; if(getcwd(szPath, sizeof(szPath)) == NULL) { perror("getcwd"); exit(1); } else { chdir(szPath); printf("set current path succ [%s]\n", szPath); } */ //chdir("/tmp");//改变工作目录到/tmp umask(0);//重设文件创建掩模 // [6] set termianl signal signal(SIGTERM, wait_close); signal(SIGHUP, restart_server); /* * Close all open file descriptors. */ if (rl.rlim_max == RLIM_INFINITY) rl.rlim_max = 1024; for (i = 0; i < rl.rlim_max; i++) close(i); /* * Attach file descriptors 0, 1, and 2 to /dev/null. */ int fd0 = open("/dev/null", O_RDWR); int fd1 = dup(0); int fd2 = dup(0); /* * Initialize the log file. */ openlog("pushserver", LOG_CONS, LOG_DAEMON); if (fd0 != 0 || fd1 != 1 || fd2 != 2) { syslog(LOG_ERR, "unexpected file descriptors %d %d %d",fd0, fd1, fd2); exit(1); } syslog(LOG_DEBUG, "daem ok "); return; }
static int exec_conf(void) { int pipefd[2], stat, size; struct sigaction sa; sigset_t sset, osset; sigemptyset(&sset); sigaddset(&sset, SIGINT); sigprocmask(SIG_BLOCK, &sset, &osset); signal(SIGINT, SIG_DFL); sa.sa_handler = winch_handler; sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART; sigaction(SIGWINCH, &sa, NULL); *argptr++ = NULL; pipe(pipefd); pid = fork(); if (pid == 0) { sigprocmask(SIG_SETMASK, &osset, NULL); dup2(pipefd[1], 2); close(pipefd[0]); close(pipefd[1]); execv(args[0], args); _exit(EXIT_FAILURE); } close(pipefd[1]); bufptr = input_buf; while (1) { size = input_buf + sizeof(input_buf) - bufptr; size = read(pipefd[0], bufptr, size); if (size <= 0) { if (size < 0) { if (errno == EINTR || errno == EAGAIN) continue; perror("read"); } break; } bufptr += size; } *bufptr++ = 0; close(pipefd[0]); waitpid(pid, &stat, 0); if (do_resize) { init_wsize(); do_resize = 0; sigprocmask(SIG_SETMASK, &osset, NULL); return -1; } if (WIFSIGNALED(stat)) { printf("\finterrupted(%d)\n", WTERMSIG(stat)); exit(1); } #if 0 printf("\fexit state: %d\nexit data: '%s'\n", WEXITSTATUS(stat), input_buf); sleep(1); #endif sigpending(&sset); if (sigismember(&sset, SIGINT)) { printf("\finterrupted\n"); exit(1); } sigprocmask(SIG_SETMASK, &osset, NULL); return WEXITSTATUS(stat); }
int main( int argc, char **argv ) { int status, retval, num_tests = 1, tmp; int EventSet1 = PAPI_NULL; long long **values; long long elapsed_us, elapsed_cyc, elapsed_virt_us, elapsed_virt_cyc; char event_name[PAPI_MAX_STR_LEN];; const PAPI_hw_info_t *hw_info; const PAPI_component_info_t *cmpinfo; pid_t pid; /* Fork before doing anything with the PMU */ setbuf(stdout,NULL); pid = fork( ); if ( pid < 0 ) test_fail( __FILE__, __LINE__, "fork()", PAPI_ESYS ); if ( pid == 0 ) exit( wait_for_attach_and_loop( ) ); tests_quiet( argc, argv ); /* Set TESTS_QUIET variable */ /* Master only process below here */ retval = PAPI_library_init( PAPI_VER_CURRENT ); if ( retval != PAPI_VER_CURRENT ) test_fail_exit( __FILE__, __LINE__, "PAPI_library_init", retval ); if ( ( cmpinfo = PAPI_get_component_info( 0 ) ) == NULL ) test_fail_exit( __FILE__, __LINE__, "PAPI_get_component_info", 0 ); if ( cmpinfo->attach == 0 ) test_skip( __FILE__, __LINE__, "Platform does not support attaching", 0 ); hw_info = PAPI_get_hardware_info( ); if ( hw_info == NULL ) test_fail_exit( __FILE__, __LINE__, "PAPI_get_hardware_info", 0 ); /* add PAPI_TOT_CYC and one of the events in PAPI_FP_INS, PAPI_FP_OPS or PAPI_TOT_INS, depending on the availability of the event on the platform */ retval = PAPI_create_eventset(&EventSet1); if ( retval != PAPI_OK ) test_fail_exit( __FILE__, __LINE__, "PAPI_attach", retval ); /* Force addition of component */ retval = PAPI_assign_eventset_component( EventSet1, 0 ); if ( retval != PAPI_OK ) test_fail( __FILE__, __LINE__, "PAPI_assign_eventset_component", retval ); /* The following call causes this test to fail for perf_events */ retval = PAPI_attach( EventSet1, ( unsigned long ) pid ); if ( retval != PAPI_OK ) test_fail_exit( __FILE__, __LINE__, "PAPI_attach", retval ); sprintf(event_name,"PAPI_TOT_CYC"); retval = PAPI_add_event(EventSet1, PAPI_TOT_CYC); if ( retval != PAPI_OK ) test_fail_exit( __FILE__, __LINE__, "PAPI_add_event", retval ); retval = PAPI_add_event(EventSet1, PAPI_FP_INS); if ( retval == PAPI_ENOEVNT ) { test_warn( __FILE__, __LINE__, "PAPI_FP_INS", retval); } else if ( retval != PAPI_OK ) { test_fail_exit( __FILE__, __LINE__, "PAPI_add_event", retval ); } values = allocate_test_space( 1, 2); elapsed_us = PAPI_get_real_usec( ); elapsed_cyc = PAPI_get_real_cyc( ); elapsed_virt_us = PAPI_get_virt_usec( ); elapsed_virt_cyc = PAPI_get_virt_cyc( ); printf("must_ptrace is %d\n",cmpinfo->attach_must_ptrace); pid_t child = wait( &status ); printf( "Debugger exited wait() with %d\n",child ); if (WIFSTOPPED( status )) { printf( "Child has stopped due to signal %d (%s)\n", WSTOPSIG( status ), strsignal(WSTOPSIG( status )) ); } if (WIFSIGNALED( status )) { printf( "Child %ld received signal %d (%s)\n", (long)child, WTERMSIG(status) , strsignal(WTERMSIG( status )) ); } printf("After %d\n",retval); retval = PAPI_start( EventSet1 ); if ( retval != PAPI_OK ) test_fail_exit( __FILE__, __LINE__, "PAPI_start", retval ); printf("Continuing\n"); #if defined(__FreeBSD__) if ( ptrace( PT_CONTINUE, pid, (caddr_t) 1, 0 ) == -1 ) { #else if ( ptrace( PTRACE_CONT, pid, NULL, NULL ) == -1 ) { #endif perror( "ptrace(PTRACE_CONT)" ); return 1; } do { child = wait( &status ); printf( "Debugger exited wait() with %d\n", child); if (WIFSTOPPED( status )) { printf( "Child has stopped due to signal %d (%s)\n", WSTOPSIG( status ), strsignal(WSTOPSIG( status )) ); } if (WIFSIGNALED( status )) { printf( "Child %ld received signal %d (%s)\n", (long)child, WTERMSIG(status) , strsignal(WTERMSIG( status )) ); } } while (!WIFEXITED( status )); printf("Child exited with value %d\n",WEXITSTATUS(status)); if (WEXITSTATUS(status) != 0) test_fail_exit( __FILE__, __LINE__, "Exit status of child to attach to", PAPI_EMISC); retval = PAPI_stop( EventSet1, values[0] ); if ( retval != PAPI_OK ) test_fail_exit( __FILE__, __LINE__, "PAPI_stop", retval ); elapsed_virt_us = PAPI_get_virt_usec( ) - elapsed_virt_us; elapsed_virt_cyc = PAPI_get_virt_cyc( ) - elapsed_virt_cyc; elapsed_us = PAPI_get_real_usec( ) - elapsed_us; elapsed_cyc = PAPI_get_real_cyc( ) - elapsed_cyc; retval = PAPI_cleanup_eventset(EventSet1); if (retval != PAPI_OK) test_fail_exit( __FILE__, __LINE__, "PAPI_cleanup_eventset", retval ); retval = PAPI_destroy_eventset(&EventSet1); if (retval != PAPI_OK) test_fail_exit( __FILE__, __LINE__, "PAPI_destroy_eventset", retval ); printf( "Test case: 3rd party attach start, stop.\n" ); printf( "-----------------------------------------------\n" ); tmp = PAPI_get_opt( PAPI_DEFDOM, NULL ); printf( "Default domain is: %d (%s)\n", tmp, stringify_all_domains( tmp ) ); tmp = PAPI_get_opt( PAPI_DEFGRN, NULL ); printf( "Default granularity is: %d (%s)\n", tmp, stringify_granularity( tmp ) ); printf( "Using %d iterations of c += a*b\n", NUM_FLOPS ); printf ( "-------------------------------------------------------------------------\n" ); printf( "Test type : \t 1\n" ); printf( TAB1, "PAPI_TOT_CYC : \t", ( values[0] )[0] ); printf( TAB1, "PAPI_FP_INS : \t", ( values[0] )[1] ); printf( TAB1, "Real usec : \t", elapsed_us ); printf( TAB1, "Real cycles : \t", elapsed_cyc ); printf( TAB1, "Virt usec : \t", elapsed_virt_us ); printf( TAB1, "Virt cycles : \t", elapsed_virt_cyc ); printf ( "-------------------------------------------------------------------------\n" ); printf( "Verification: none\n" ); test_pass( __FILE__, values, num_tests ); exit( 1 ); }
int pload (int tbl) { int c = 0, i, status; if (verbose > 0) { fprintf (stderr, "Starting %d children to load %s", children, tdefs[tbl].comment); } for (c = 0; c < children; c++) { pids[c] = SPAWN (); if (pids[c] == -1) { perror ("Child loader not created"); kill_load (); exit (-1); } else if (pids[c] == 0) /* CHILD */ { SET_HANDLER (stop_proc); verbose = 0; partial (tbl, c+1); exit (0); } else if (verbose > 0) /* PARENT */ fprintf (stderr, "."); } if (verbose > 0) fprintf (stderr, "waiting..."); c = children; while (c) { i = WAIT (&status, pids[c - 1]); if (i == -1 && children) { if (errno == ECHILD) fprintf (stderr, "\nCould not wait on pid %d\n", pids[c - 1]); else if (errno == EINTR) fprintf (stderr, "\nProcess %d stopped abnormally\n", pids[c - 1]); else if (errno == EINVAL) fprintf (stderr, "\nProgram bug\n"); } if (! WIFEXITED(status)) { (void) fprintf(stderr, "\nProcess %d: ", i); if (WIFSIGNALED(status)) { (void) fprintf(stderr, "rcvd signal %d\n", WTERMSIG(status)); } else if (WIFSTOPPED(status)) { (void) fprintf(stderr, "stopped, signal %d\n", WSTOPSIG(status)); } } c--; } if (verbose > 0) fprintf (stderr, "done\n"); return (0); }
/* Monitoring the subprocess end and get the return value */ static void * monitor (void *arg) { subprocess_t *p = arg; struct timespec start_time; /* Initializing the pipes () */ int stdin_pipe[2]; /* '0' = child_read, '1' = parent_write */ int stdout_pipe[2]; /* '0' = parent_read, '1' = child_write */ int stderr_pipe[2]; /* '0' = parent_read, '1' = child_write */ CHECK_ERROR (((pipe (stdin_pipe) == -1) || (pipe (stdout_pipe) == -1) || (pipe (stderr_pipe) == -1)), "pipe initialization failed"); /* We create a child process running the subprocess and we wait for * it to finish. If a timeout elapsed the child is killed. Waiting * is done using sigtimedwait(). Race condition is avoided by * blocking the SIGCHLD signal before fork() and storing it into the * buffer while starting the timer in a separate pthread. */ /* Blocking SIGCHLD before forking */ sigset_t mask; CHECK_ERROR ((sigemptyset (&mask) == -1), "sigemptyset failed"); CHECK_ERROR ((sigaddset (&mask, SIGCHLD) == -1), "sigaddset failed"); CHECK_ERROR ((sigprocmask (SIG_BLOCK, &mask, NULL) == -1), "sigprocmask failed"); /* Getting start time of the subprocess (profiling information) */ CHECK_ERROR ((clock_gettime (CLOCK_MONOTONIC, &start_time) == -1), "getting start time failed"); /* Forking the process */ CHECK_ERROR (((p->pid = fork ()) == -1), "fork failed"); if (p->pid == 0) /***** Child process *****/ { /* TODO: What if the child_monitor fails miserably ? It should * be signaled in the parent stderr and not in the child * stderr. */ CHECK_ERROR ((child_monitor (p, stdin_pipe, stdout_pipe, stderr_pipe) == RETURN_FAILURE), "child monitor failed"); } else /***** Parent process *****/ { int status; pthread_t watchdog_pthread, io_pthread; struct rusage usage; CHECK_ERROR ((close (stdin_pipe[0]) == -1), "close(stdin[0]) failed"); CHECK_ERROR (((p->stdin = fdopen (stdin_pipe[1], "w")) == NULL), "fdopen(stdin[1]) failed"); CHECK_ERROR ((close (stdout_pipe[1]) == -1), "close(stdout[1]) failed"); CHECK_ERROR (((p->stdout = fdopen (stdout_pipe[0], "r")) == NULL), "fdopen(stdout[0]) failed"); CHECK_ERROR ((close (stderr_pipe[1]) == -1), "close(stderr[1]) failed"); CHECK_ERROR (((p->stderr = fdopen (stderr_pipe[0], "r")) == NULL), "fdopen(stderr[0]) failed"); /* Running a watchdog to timeout the subprocess */ if ((p->limits) && (p->limits->timeout > 0)) CHECK_ERROR ((pthread_create (&watchdog_pthread, NULL, watchdog, p) != 0), "watchdog creation failed"); /* Running the io monitor to watch stdout and stderr */ CHECK_ERROR ((pthread_create (&io_pthread, NULL, io_monitor, p) != 0), "io_monitor creation failed"); p->status = RUNNING; /* Waiting for synchronization with monitored process */ CHECK_ERROR (wait4 (p->pid, &status, 0, &usage) == -1, "wait failed"); /* Filtering syscalls with ptrace */ if ((p->limits != NULL) && (p->limits->syscalls[0] > 0)) { if (syscall_filter (p, &status, &usage) == RETURN_FAILURE) goto fail; } /***** The subprocess is finished now *****/ /* Getting end time of the subprocess (profiling information) */ struct timespec tmp_time, end_time; CHECK_ERROR ((clock_gettime (CLOCK_MONOTONIC, &end_time) == -1), "getting end time failed"); tmp_time = timespec_diff (start_time, end_time); p->real_time_usec = (time_t) (tmp_time.tv_sec * 1000000 + tmp_time.tv_nsec / 1000); /* Finding out what the status and retval are really */ if (WIFEXITED (status)) { /* Exited normally */ p->status = TERMINATED; p->retval = WEXITSTATUS (status); /* Return value */ } else if (WIFSIGNALED (status)) { p->retval = WTERMSIG (status); /* Kill signal */ if (p->status < TERMINATED) { /* Trying to guess why by looking at errno value */ switch (WTERMSIG (status)) { case SIGSEGV: p->status = MEMORYOUT; break; default: p->status = KILLED; } } /* FIXME: It may be interesting to store the termination signal * into another variable and to 'p->retval = errno' */ } else if (WIFSTOPPED (status)) { p->status = STOPPED; p->retval = WSTOPSIG (status); /* Stop signal */ } else if (WIFCONTINUED (status)) { p->status = RUNNING; p->retval = 0; /* Process is still running */ } fail: /* Cleaning the io_monitor */ pthread_cancel (io_pthread); /* Cleaning the watchdog if not already exited */ if ((p->limits) && (p->limits->timeout > 0)) pthread_cancel (watchdog_pthread); /* Cleaning and setting the profile information */ /* User time in us */ p->user_time_usec = usage.ru_utime.tv_sec * 1000 + usage.ru_utime.tv_usec; /* System time in us */ p->sys_time_usec = usage.ru_stime.tv_sec * 1000 + usage.ru_stime.tv_usec; /* Memory usage */ p->memory_kbytes = usage.ru_maxrss; } return NULL; }
int runProgram() { //printf("runProgram()\n"); if (global.params.verbose) { printf("%s", global.params.exefile); for (size_t i = 0; i < global.params.runargs_length; i++) printf(" %s", (char *)global.params.runargs[i]); printf("\n"); } // Build argv[] Strings argv; argv.push(global.params.exefile); for (size_t i = 0; i < global.params.runargs_length; i++) { char *a = global.params.runargs[i]; #if _WIN32 // BUG: what about " appearing in the string? if (strchr(a, ' ')) { char *b = (char *)mem.malloc(3 + strlen(a)); sprintf(b, "\"%s\"", a); a = b; } #endif argv.push(a); } argv.push(NULL); #if _WIN32 char *ex = FileName::name(global.params.exefile); if (ex == global.params.exefile) ex = FileName::combine(".", ex); else ex = global.params.exefile; // spawnlp returns intptr_t in some systems, not int return spawnv(0,ex,argv.tdata()); #elif linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun pid_t childpid; int status; childpid = fork(); if (childpid == 0) { char *fn = argv[0]; if (!FileName::absolute(fn)) { // Make it "./fn" fn = FileName::combine(".", fn); } execv(fn, argv.tdata()); perror(fn); // failed to execute return -1; } waitpid(childpid, &status, 0); if (WIFEXITED(status)) { status = WEXITSTATUS(status); //printf("--- errorlevel %d\n", status); } else if (WIFSIGNALED(status)) { printf("--- killed by signal %d\n", WTERMSIG(status)); status = 1; } return status; #else assert(0); #endif }
int main(int args, char *argv[]){ if(args<4){ ToPipe("IE ERROR Not enough arguments."); return 1; } int TimeLimit, MemoryLimit, InputFileId, FileId; struct timeval start,finish; struct sigaction signalAction; pid_t w; int status; long long t_sec, t_usec; FileId = atoi(argv[1]), InputFileId = atoi(argv[2]), TimeLimit = atoi(argv[3]), MemoryLimit = atoi(argv[4]); signalAction.sa_flags = SA_NOCLDSTOP | SA_NOCLDWAIT; signalAction.sa_handler = signalHandler; if(sigaction(SIGALRM, &signalAction, NULL)==-1){ ToPipe("IE ERROR Could not register handler for sigalrm"); return 1; } if(sigaction(SIGXCPU, &signalAction, NULL)==-1){ ToPipe("IE ERROR Could not register handler fo rSIGXCPU"); return 1; } gettimeofday(&start,NULL); cpid = fork(); if (cpid == -1) { perror("fork"); exit(EXIT_FAILURE); } if (cpid == 0) { /* Code executed by child */ pid_t ChildProcessId = getpid(); passwd* UserDetails = getpwnam("nobody"); char dir[10]; sprintf(dir, "%s%d/",FILEPATH,FileId); //ToPipe(dir); if( chdir(dir) == -1){ printf("%d", errno); ToPipe("IE ERROR Cannot change directory to that of file"); return 1; } //ToPipe(get_current_dir_name()); /*if(chroot(get_current_dir_name())!=0){ ToPipe("IE ERROR Cannot jail the program"); return 1; }*/ if(( setpgid( ChildProcessId, ChildProcessId) ) == -1 ){ ToPipe("IE ERROR process group could not be created\n"); return 1; } if(UserDetails!=NULL){ gid_t GroupId = UserDetails->pw_gid; if( GroupId > 0 ){ setgid( GroupId ); } else{ ToPipe("IE ERROR Could not set groupid as groupid is invalid\n"); return 1; } uid_t UserId = UserDetails->pw_uid; if( UserId > 0 ){ setuid(UserId); } else{ ToPipe("IE ERROR Failed to set userid as it is invalid\n"); return 1; } } else{ ToPipe("IE ERROR No user id associated with user nobody\n"); return 1; } char InputFile[10], TestCaseFile[10], OutputFile[10]; sprintf(InputFile, "main"); sprintf(TestCaseFile, "%d.txt", InputFileId); sprintf(OutputFile, "%do.txt", InputFileId); if(freopen(TestCaseFile, "r", stdin)==NULL){ ToPipe("IE ERROR Could not open test case file\n"); } if(freopen(OutputFile, "w", stdout)==NULL){ ToPipe("IE ERROR Could not open output file\n"); } if(freopen("/dev/null", "w", stderr)==NULL){ ToPipe("IE ERROR Could not redirect error stream to null\n"); } setResourceLimitWrapper(TimeLimit, MemoryLimit); alarm(TimeLimit); if(execl(InputFile,InputFile,(char *) NULL) == -1){ fclose(stdout); ToPipe("IE ERROR File not present or some other error."); } } else { /* Code executed by parent */ struct rusage resourceUsage; w = wait4 (cpid, &status, NULL, &resourceUsage); gettimeofday(&finish,NULL); t_sec = finish.tv_sec-start.tv_sec; t_sec=finish.tv_sec-start.tv_sec; t_usec=finish.tv_usec-start.tv_usec; if(t_usec<0){ t_sec--; t_usec+=1000000; } timeval tv = resourceUsage.ru_utime; float SysTime = (float)( tv.tv_sec * 1000000 + (int) tv.tv_usec ) / 1000000 ; float TimeUsed = (float)( t_sec * 1000000 + (int) t_usec ) / 1000000 ; if( WIFEXITED(status) == true ){ if( WEXITSTATUS(status) !=0 ){ ToPipe("RE NZEC"); } else{ ToPipe("AC"); } } else if( WIFSIGNALED(status) == true ){ if (WTERMSIG (status) == SIGKILL || WTERMSIG(status) == SIGALRM) ToPipe("TLE"); else if (WTERMSIG (status) == SIGXFSZ) ToPipe("RE SIGXFSZ"); else if (WTERMSIG (status) == SIGSEGV) ToPipe("RE SIGSEGV"); else if (WTERMSIG (status) == SIGFPE) ToPipe("RE SIGFPE"); else if (WTERMSIG (status) == SIGABRT) ToPipe("RE SIGABRT"); else if (WTERMSIG (status) == SIGHUP) ToPipe("IE SIGHUP"); else if (WTERMSIG (status) == SIGPIPE) ToPipe("IE SIGPIPE"); else{ ToPipe("RE OTHER"); printf("%d\n", WTERMSIG(status)); } } char tmp[10]; sprintf(tmp, "%0.4f", TimeUsed); ToPipe(tmp); printf("%d %d\n", (int)tv.tv_sec, (int)tv.tv_usec); } }
int master_loop(char **argv, char **environ) { uint64_t tmp_counter; struct timeval last_respawn; int last_respawn_rate = 0; int pid_found = 0; pid_t diedpid; int waitpid_status; uint8_t uwsgi_signal; time_t last_request_timecheck = 0, now = 0; uint64_t last_request_count = 0; pthread_t logger_thread; pthread_t cache_sweeper; pthread_t cache_udp_server; pthread_t channels_loop; #ifdef UWSGI_UDP int udp_fd = -1; #ifdef UWSGI_MULTICAST char *cluster_opt_buf = NULL; size_t cluster_opt_size = 4; #endif #endif #ifdef UWSGI_SNMP int snmp_fd = -1; #endif int i = 0; int rlen; int check_interval = 1; struct uwsgi_rb_timer *min_timeout; struct rb_root *rb_timers = uwsgi_init_rb_timer(); if (uwsgi.procname_master) { uwsgi_set_processname(uwsgi.procname_master); } else if (uwsgi.procname) { uwsgi_set_processname(uwsgi.procname); } else if (uwsgi.auto_procname) { uwsgi_set_processname("uWSGI master"); } uwsgi.current_time = uwsgi_now(); uwsgi_unix_signal(SIGTSTP, suspend_resume_them_all); uwsgi_unix_signal(SIGHUP, grace_them_all); if (uwsgi.die_on_term) { uwsgi_unix_signal(SIGTERM, kill_them_all); uwsgi_unix_signal(SIGQUIT, reap_them_all); } else { uwsgi_unix_signal(SIGTERM, reap_them_all); uwsgi_unix_signal(SIGQUIT, kill_them_all); } uwsgi_unix_signal(SIGINT, kill_them_all); uwsgi_unix_signal(SIGUSR1, stats); if (uwsgi.auto_snapshot) { uwsgi_unix_signal(SIGURG, uwsgi_restore_auto_snapshot); } atexit(uwsgi_master_cleanup_hooks); uwsgi.master_queue = event_queue_init(); /* route signals to workers... */ #ifdef UWSGI_DEBUG uwsgi_log("adding %d to signal poll\n", uwsgi.shared->worker_signal_pipe[0]); #endif event_queue_add_fd_read(uwsgi.master_queue, uwsgi.shared->worker_signal_pipe[0]); #ifdef UWSGI_SPOOLER if (uwsgi.spoolers) { event_queue_add_fd_read(uwsgi.master_queue, uwsgi.shared->spooler_signal_pipe[0]); } #endif if (uwsgi.mules_cnt > 0) { event_queue_add_fd_read(uwsgi.master_queue, uwsgi.shared->mule_signal_pipe[0]); } if (uwsgi.log_master) { uwsgi.log_master_buf = uwsgi_malloc(uwsgi.log_master_bufsize); if (!uwsgi.threaded_logger) { #ifdef UWSGI_DEBUG uwsgi_log("adding %d to master logging\n", uwsgi.shared->worker_log_pipe[0]); #endif event_queue_add_fd_read(uwsgi.master_queue, uwsgi.shared->worker_log_pipe[0]); } else { if (pthread_create(&logger_thread, NULL, logger_thread_loop, NULL)) { uwsgi_error("pthread_create()"); uwsgi_log("falling back to non-threaded logger...\n"); event_queue_add_fd_read(uwsgi.master_queue, uwsgi.shared->worker_log_pipe[0]); uwsgi.threaded_logger = 0; } } #ifdef UWSGI_ALARM // initialize the alarm subsystem uwsgi_alarms_init(); #endif } #ifdef UWSGI_SSL uwsgi_start_legions(); #endif if (uwsgi.cache_max_items > 0 && !uwsgi.cache_no_expire) { if (pthread_create(&cache_sweeper, NULL, cache_sweeper_loop, NULL)) { uwsgi_error("pthread_create()"); uwsgi_log("unable to run the cache sweeper !!!\n"); } else { uwsgi_log("cache sweeper thread enabled\n"); } } if (uwsgi.cache_max_items > 0 && uwsgi.cache_udp_server) { if (pthread_create(&cache_udp_server, NULL, cache_udp_server_loop, NULL)) { uwsgi_error("pthread_create()"); uwsgi_log("unable to run the cache udp server !!!\n"); } else { uwsgi_log("cache udp server thread enabled\n"); } } if (uwsgi.channels) { if (pthread_create(&channels_loop, NULL, uwsgi_channels_loop, NULL)) { uwsgi_error("pthread_create()"); uwsgi_log("unable to run the channels dispatcher thread !!!\n"); } else { uwsgi_log("channels dispatcher thread enabled\n"); } } uwsgi.wsgi_req->buffer = uwsgi.workers[0].cores[0].buffer; if (uwsgi.has_emperor) { event_queue_add_fd_read(uwsgi.master_queue, uwsgi.emperor_fd); } if (uwsgi.zerg_server) { uwsgi.zerg_server_fd = bind_to_unix(uwsgi.zerg_server, uwsgi.listen_queue, 0, 0); event_queue_add_fd_read(uwsgi.master_queue, uwsgi.zerg_server_fd); uwsgi_log("*** Zerg server enabled on %s ***\n", uwsgi.zerg_server); } if (uwsgi.stats) { char *tcp_port = strchr(uwsgi.stats, ':'); if (tcp_port) { // disable deferred accept for this socket int current_defer_accept = uwsgi.no_defer_accept; uwsgi.no_defer_accept = 1; uwsgi.stats_fd = bind_to_tcp(uwsgi.stats, uwsgi.listen_queue, tcp_port); uwsgi.no_defer_accept = current_defer_accept; } else { uwsgi.stats_fd = bind_to_unix(uwsgi.stats, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket); } event_queue_add_fd_read(uwsgi.master_queue, uwsgi.stats_fd); uwsgi_log("*** Stats server enabled on %s fd: %d ***\n", uwsgi.stats, uwsgi.stats_fd); } if (uwsgi.requested_stats_pushers) { if (!uwsgi_thread_new(uwsgi_stats_pusher_loop)) { uwsgi_log("!!! unable to spawn stats pusher thread !!!\n"); exit(1); } } #ifdef UWSGI_UDP if (uwsgi.udp_socket) { udp_fd = bind_to_udp(uwsgi.udp_socket, 0, 0); if (udp_fd < 0) { uwsgi_log("unable to bind to udp socket. SNMP and cluster management services will be disabled.\n"); } else { uwsgi_log("UDP server enabled.\n"); event_queue_add_fd_read(uwsgi.master_queue, udp_fd); } } #ifdef UWSGI_MULTICAST if (uwsgi.cluster) { event_queue_add_fd_read(uwsgi.master_queue, uwsgi.cluster_fd); cluster_opt_buf = uwsgi_setup_clusterbuf(&cluster_opt_size); } #endif #endif #ifdef UWSGI_SNMP snmp_fd = uwsgi_setup_snmp(); #endif if (uwsgi.cheap) { uwsgi_add_sockets_to_queue(uwsgi.master_queue, -1); for (i = 1; i <= uwsgi.numproc; i++) { uwsgi.workers[i].cheaped = 1; } uwsgi_log("cheap mode enabled: waiting for socket connection...\n"); } // spawn mules for (i = 0; i < uwsgi.mules_cnt; i++) { size_t mule_patch_size = 0; uwsgi.mules[i].patch = uwsgi_string_get_list(&uwsgi.mules_patches, i, &mule_patch_size); uwsgi_mule(i + 1); } // spawn gateways for (i = 0; i < ushared->gateways_cnt; i++) { if (ushared->gateways[i].pid == 0) { gateway_respawn(i); } } // spawn daemons uwsgi_daemons_spawn_all(); // first subscription uwsgi_subscribe_all(0, 1); // sync the cache store if needed if (uwsgi.cache_store && uwsgi.cache_filesize) { if (msync(uwsgi.cache_items, uwsgi.cache_filesize, MS_ASYNC)) { uwsgi_error("msync()"); } } if (uwsgi.queue_store && uwsgi.queue_filesize) { if (msync(uwsgi.queue_header, uwsgi.queue_filesize, MS_ASYNC)) { uwsgi_error("msync()"); } } // update touches timestamps uwsgi_check_touches(uwsgi.touch_reload); uwsgi_check_touches(uwsgi.touch_logrotate); uwsgi_check_touches(uwsgi.touch_logreopen); // setup cheaper algos uwsgi.cheaper_algo = uwsgi_cheaper_algo_spare; if (uwsgi.requested_cheaper_algo) { uwsgi.cheaper_algo = NULL; struct uwsgi_cheaper_algo *uca = uwsgi.cheaper_algos; while (uca) { if (!strcmp(uca->name, uwsgi.requested_cheaper_algo)) { uwsgi.cheaper_algo = uca->func; break; } uca = uca->next; } if (!uwsgi.cheaper_algo) { uwsgi_log("unable to find requested cheaper algorithm, falling back to spare\n"); uwsgi.cheaper_algo = uwsgi_cheaper_algo_spare; } } // here really starts the master loop for (;;) { //uwsgi_log("uwsgi.ready_to_reload %d %d\n", uwsgi.ready_to_reload, uwsgi.numproc); // run master_cycle hook for every plugin for (i = 0; i < uwsgi.gp_cnt; i++) { if (uwsgi.gp[i]->master_cycle) { uwsgi.gp[i]->master_cycle(); } } for (i = 0; i < 256; i++) { if (uwsgi.p[i]->master_cycle) { uwsgi.p[i]->master_cycle(); } } uwsgi_daemons_smart_check(); if (uwsgi.to_outworld) { //uwsgi_log("%d/%d\n", uwsgi.lazy_respawned, uwsgi.numproc); if (uwsgi.lazy_respawned >= uwsgi.marked_workers || uwsgi.lazy_respawned >= uwsgi.numproc) { uwsgi.to_outworld = 0; uwsgi.master_mercy = 0; uwsgi.lazy_respawned = 0; } } if (uwsgi_master_check_mercy()) return 0; if (uwsgi.respawn_workers) { for (i = 1; i <= uwsgi.respawn_workers; i++) { if (uwsgi_respawn_worker(i)) return 0; } uwsgi.respawn_workers = 0; } if (uwsgi.restore_snapshot) { uwsgi_master_restore_snapshot(); continue; } // cheaper management if (uwsgi.cheaper && !uwsgi.cheap && !uwsgi.to_heaven && !uwsgi.to_hell && !uwsgi.to_outworld && !uwsgi.workers[0].suspended) { if (!uwsgi_calc_cheaper()) return 0; } if ((uwsgi.cheap || uwsgi.ready_to_die >= uwsgi.marked_workers || uwsgi.ready_to_die >= uwsgi.numproc) && uwsgi.to_hell) { // call a series of waitpid to ensure all processes (gateways, mules and daemons) are dead for (i = 0; i < (ushared->gateways_cnt + uwsgi.daemons_cnt + uwsgi.mules_cnt); i++) { diedpid = waitpid(WAIT_ANY, &waitpid_status, WNOHANG); } uwsgi_log("goodbye to uWSGI.\n"); exit(0); } if ((uwsgi.cheap || uwsgi.ready_to_reload >= uwsgi.marked_workers || uwsgi.ready_to_reload >= uwsgi.numproc) && uwsgi.to_heaven) { uwsgi_reload(argv); // never here (unless in shared library mode) return -1; } diedpid = waitpid(WAIT_ANY, &waitpid_status, WNOHANG); if (diedpid == -1) { if (errno == ECHILD) { // something did not work as expected, just assume all has been cleared if (uwsgi.to_heaven) { uwsgi.ready_to_reload = uwsgi.numproc; continue; } else if (uwsgi.to_hell) { uwsgi.ready_to_die = uwsgi.numproc; continue; } else if (uwsgi.to_outworld) { uwsgi.lazy_respawned = uwsgi.numproc; uwsgi_log("*** no workers to reload found ***\n"); continue; } diedpid = 0; } else { uwsgi_error("waitpid()"); /* here is better to reload all the uWSGI stack */ uwsgi_log("something horrible happened...\n"); reap_them_all(0); exit(1); } } if (diedpid == 0) { /* all processes ok, doing status scan after N seconds */ check_interval = uwsgi.shared->options[UWSGI_OPTION_MASTER_INTERVAL]; if (!check_interval) check_interval = 1; // add unregistered file monitors // locking is not needed as monitors can only increase for (i = 0; i < ushared->files_monitored_cnt; i++) { if (!ushared->files_monitored[i].registered) { ushared->files_monitored[i].fd = event_queue_add_file_monitor(uwsgi.master_queue, ushared->files_monitored[i].filename, &ushared->files_monitored[i].id); ushared->files_monitored[i].registered = 1; } } // add unregistered timers // locking is not needed as timers can only increase for (i = 0; i < ushared->timers_cnt; i++) { if (!ushared->timers[i].registered) { ushared->timers[i].fd = event_queue_add_timer(uwsgi.master_queue, &ushared->timers[i].id, ushared->timers[i].value); ushared->timers[i].registered = 1; } } // add unregistered rb_timers // locking is not needed as rb_timers can only increase for (i = 0; i < ushared->rb_timers_cnt; i++) { if (!ushared->rb_timers[i].registered) { ushared->rb_timers[i].uwsgi_rb_timer = uwsgi_add_rb_timer(rb_timers, uwsgi_now() + ushared->rb_timers[i].value, &ushared->rb_timers[i]); ushared->rb_timers[i].registered = 1; } } int interesting_fd = -1; if (ushared->rb_timers_cnt > 0) { min_timeout = uwsgi_min_rb_timer(rb_timers); if (min_timeout == NULL) { check_interval = uwsgi.shared->options[UWSGI_OPTION_MASTER_INTERVAL]; } else { check_interval = min_timeout->key - uwsgi_now(); if (check_interval <= 0) { expire_rb_timeouts(rb_timers); check_interval = 0; } } } // wait for event rlen = event_queue_wait(uwsgi.master_queue, check_interval, &interesting_fd); if (rlen == 0) { if (ushared->rb_timers_cnt > 0) { expire_rb_timeouts(rb_timers); } } // check uwsgi-cron table if (ushared->cron_cnt) { uwsgi_manage_signal_cron(uwsgi_now()); } if (uwsgi.crons) { uwsgi_manage_command_cron(uwsgi_now()); } // check for probes if (ushared->probes_cnt > 0) { uwsgi_lock(uwsgi.probe_table_lock); for (i = 0; i < ushared->probes_cnt; i++) { if (interesting_fd == -1) { // increment cycles ushared->probes[i].cycles++; } if (ushared->probes[i].func(interesting_fd, &ushared->probes[i])) { uwsgi_route_signal(ushared->probes[i].sig); } } uwsgi_unlock(uwsgi.probe_table_lock); } if (rlen > 0) { if (uwsgi.log_master && !uwsgi.threaded_logger) { if (interesting_fd == uwsgi.shared->worker_log_pipe[0]) { uwsgi_master_log(); goto health_cycle; } } if (uwsgi.stats && uwsgi.stats_fd > -1) { if (interesting_fd == uwsgi.stats_fd) { uwsgi_send_stats(uwsgi.stats_fd, uwsgi_master_generate_stats); goto health_cycle; } } if (uwsgi.zerg_server) { if (interesting_fd == uwsgi.zerg_server_fd) { uwsgi_manage_zerg(uwsgi.zerg_server_fd, 0, NULL); goto health_cycle; } } if (uwsgi.has_emperor) { if (interesting_fd == uwsgi.emperor_fd) { uwsgi_master_manage_emperor(); goto health_cycle; } } if (uwsgi.cheap) { int found = 0; struct uwsgi_socket *uwsgi_sock = uwsgi.sockets; while (uwsgi_sock) { if (interesting_fd == uwsgi_sock->fd) { found = 1; uwsgi.cheap = 0; uwsgi_del_sockets_from_queue(uwsgi.master_queue); int needed = uwsgi.numproc; if (uwsgi.cheaper) { needed = uwsgi.cheaper_count; } for (i = 1; i <= needed; i++) { if (uwsgi_respawn_worker(i)) return 0; } break; } uwsgi_sock = uwsgi_sock->next; } // here is better to continue instead going to health_cycle if (found) continue; } #ifdef UWSGI_SNMP if (uwsgi.snmp_addr && interesting_fd == snmp_fd) { uwsgi_master_manage_snmp(snmp_fd); goto health_cycle; } #endif #ifdef UWSGI_UDP if (uwsgi.udp_socket && interesting_fd == udp_fd) { uwsgi_master_manage_udp(udp_fd); goto health_cycle; } #ifdef UWSGI_MULTICAST if (interesting_fd == uwsgi.cluster_fd) { if (uwsgi_get_dgram(uwsgi.cluster_fd, &uwsgi.workers[0].cores[0].req)) { goto health_cycle; } manage_cluster_message(cluster_opt_buf, cluster_opt_size); goto health_cycle; } #endif #endif int next_iteration = 0; uwsgi_lock(uwsgi.fmon_table_lock); for (i = 0; i < ushared->files_monitored_cnt; i++) { if (ushared->files_monitored[i].registered) { if (interesting_fd == ushared->files_monitored[i].fd) { struct uwsgi_fmon *uf = event_queue_ack_file_monitor(uwsgi.master_queue, interesting_fd); // now call the file_monitor handler if (uf) uwsgi_route_signal(uf->sig); break; } } } uwsgi_unlock(uwsgi.fmon_table_lock); if (next_iteration) goto health_cycle;; next_iteration = 0; uwsgi_lock(uwsgi.timer_table_lock); for (i = 0; i < ushared->timers_cnt; i++) { if (ushared->timers[i].registered) { if (interesting_fd == ushared->timers[i].fd) { struct uwsgi_timer *ut = event_queue_ack_timer(interesting_fd); // now call the file_monitor handler if (ut) uwsgi_route_signal(ut->sig); break; } } } uwsgi_unlock(uwsgi.timer_table_lock); if (next_iteration) goto health_cycle;; // check for worker signal if (interesting_fd == uwsgi.shared->worker_signal_pipe[0]) { rlen = read(interesting_fd, &uwsgi_signal, 1); if (rlen < 0) { uwsgi_error("read()"); } else if (rlen > 0) { #ifdef UWSGI_DEBUG uwsgi_log_verbose("received uwsgi signal %d from a worker\n", uwsgi_signal); #endif uwsgi_route_signal(uwsgi_signal); } else { uwsgi_log_verbose("lost connection with worker %d\n", i); close(interesting_fd); } goto health_cycle; } #ifdef UWSGI_SPOOLER // check for spooler signal if (uwsgi.spoolers) { if (interesting_fd == uwsgi.shared->spooler_signal_pipe[0]) { rlen = read(interesting_fd, &uwsgi_signal, 1); if (rlen < 0) { uwsgi_error("read()"); } else if (rlen > 0) { #ifdef UWSGI_DEBUG uwsgi_log_verbose("received uwsgi signal %d from a spooler\n", uwsgi_signal); #endif uwsgi_route_signal(uwsgi_signal); } else { uwsgi_log_verbose("lost connection with the spooler\n"); close(interesting_fd); } goto health_cycle; } } #endif // check for mules signal if (uwsgi.mules_cnt > 0) { if (interesting_fd == uwsgi.shared->mule_signal_pipe[0]) { rlen = read(interesting_fd, &uwsgi_signal, 1); if (rlen < 0) { uwsgi_error("read()"); } else if (rlen > 0) { #ifdef UWSGI_DEBUG uwsgi_log_verbose("received uwsgi signal %d from a mule\n", uwsgi_signal); #endif uwsgi_route_signal(uwsgi_signal); } else { uwsgi_log_verbose("lost connection with a mule\n"); close(interesting_fd); } goto health_cycle; } } } health_cycle: now = uwsgi_now(); if (now - uwsgi.current_time < 1) { continue; } uwsgi.current_time = now; // checking logsize if (uwsgi.logfile) { uwsgi_check_logrotate(); } // this will be incremented at (more or less) regular intervals uwsgi.master_cycles++; // recalculate requests counter on race conditions risky configurations // a bit of inaccuracy is better than locking;) if (uwsgi.numproc > 1) { tmp_counter = 0; for (i = 1; i < uwsgi.numproc + 1; i++) tmp_counter += uwsgi.workers[i].requests; uwsgi.workers[0].requests = tmp_counter; } if (uwsgi.idle > 0 && !uwsgi.cheap) { uwsgi.current_time = uwsgi_now(); if (!last_request_timecheck) last_request_timecheck = uwsgi.current_time; int busy_workers = 0; for (i = 1; i <= uwsgi.numproc; i++) { if (uwsgi.workers[i].cheaped == 0 && uwsgi.workers[i].pid > 0) { if (uwsgi.workers[i].busy == 1) { busy_workers = 1; break; } } } if (last_request_count != uwsgi.workers[0].requests) { last_request_timecheck = uwsgi.current_time; last_request_count = uwsgi.workers[0].requests; } // a bit of over-engeneering to avoid clock skews else if (last_request_timecheck < uwsgi.current_time && (uwsgi.current_time - last_request_timecheck > uwsgi.idle) && !busy_workers) { uwsgi_log("workers have been inactive for more than %d seconds (%llu-%llu)\n", uwsgi.idle, (unsigned long long) uwsgi.current_time, (unsigned long long) last_request_timecheck); uwsgi.cheap = 1; if (uwsgi.die_on_idle) { if (uwsgi.has_emperor) { char byte = 22; if (write(uwsgi.emperor_fd, &byte, 1) != 1) { uwsgi_error("write()"); kill_them_all(0); } } else { kill_them_all(0); } continue; } for (i = 1; i <= uwsgi.numproc; i++) { uwsgi.workers[i].cheaped = 1; if (uwsgi.workers[i].pid == 0) continue; kill(uwsgi.workers[i].pid, SIGKILL); if (waitpid(uwsgi.workers[i].pid, &waitpid_status, 0) < 0) { if (errno != ECHILD) uwsgi_error("waitpid()"); } } uwsgi_add_sockets_to_queue(uwsgi.master_queue, -1); uwsgi_log("cheap mode enabled: waiting for socket connection...\n"); last_request_timecheck = 0; continue; } } check_interval = uwsgi.shared->options[UWSGI_OPTION_MASTER_INTERVAL]; if (!check_interval) check_interval = 1; // get listen_queue status struct uwsgi_socket *uwsgi_sock = uwsgi.sockets; while (uwsgi_sock) { if (uwsgi_sock->family == AF_INET) { uwsgi_sock->queue = uwsgi_get_tcp_info(uwsgi_sock->fd); } #ifdef __linux__ #ifdef SIOBKLGQ else if (uwsgi_sock->family == AF_UNIX) { uwsgi_sock->queue = get_linux_unbit_SIOBKLGQ(uwsgi_sock->fd); } #endif #endif uwsgi_sock = uwsgi_sock->next; } for (i = 1; i <= uwsgi.numproc; i++) { /* first check for harakiri */ if (uwsgi.workers[i].harakiri > 0) { if (uwsgi.workers[i].harakiri < (time_t) uwsgi.current_time) { trigger_harakiri(i); } } /* then user-defined harakiri */ if (uwsgi.workers[i].user_harakiri > 0) { if (uwsgi.workers[i].user_harakiri < (time_t) uwsgi.current_time) { trigger_harakiri(i); } } // then for evil memory checkers if (uwsgi.evil_reload_on_as) { if ((rlim_t) uwsgi.workers[i].vsz_size >= uwsgi.evil_reload_on_as) { uwsgi_log("*** EVIL RELOAD ON WORKER %d ADDRESS SPACE: %lld (pid: %d) ***\n", i, (long long) uwsgi.workers[i].vsz_size, uwsgi.workers[i].pid); kill(uwsgi.workers[i].pid, SIGKILL); uwsgi.workers[i].vsz_size = 0; } } if (uwsgi.evil_reload_on_rss) { if ((rlim_t) uwsgi.workers[i].rss_size >= uwsgi.evil_reload_on_rss) { uwsgi_log("*** EVIL RELOAD ON WORKER %d RSS: %lld (pid: %d) ***\n", i, (long long) uwsgi.workers[i].rss_size, uwsgi.workers[i].pid); kill(uwsgi.workers[i].pid, SIGKILL); uwsgi.workers[i].rss_size = 0; } } // need to find a better way //uwsgi.workers[i].last_running_time = uwsgi.workers[i].running_time; } for (i = 0; i < ushared->gateways_cnt; i++) { if (ushared->gateways_harakiri[i] > 0) { if (ushared->gateways_harakiri[i] < (time_t) uwsgi.current_time) { if (ushared->gateways[i].pid > 0) { kill(ushared->gateways[i].pid, SIGKILL); } ushared->gateways_harakiri[i] = 0; } } } for (i = 0; i < uwsgi.mules_cnt; i++) { if (uwsgi.mules[i].harakiri > 0) { if (uwsgi.mules[i].harakiri < (time_t) uwsgi.current_time) { uwsgi_log("*** HARAKIRI ON MULE %d HANDLING SIGNAL %d (pid: %d) ***\n", i + 1, uwsgi.mules[i].signum, uwsgi.mules[i].pid); kill(uwsgi.mules[i].pid, SIGKILL); uwsgi.mules[i].harakiri = 0; } } } #ifdef UWSGI_SPOOLER struct uwsgi_spooler *uspool = uwsgi.spoolers; while (uspool) { if (uspool->harakiri > 0 && uspool->harakiri < (time_t) uwsgi.current_time) { uwsgi_log("*** HARAKIRI ON THE SPOOLER (pid: %d) ***\n", uspool->pid); kill(uspool->pid, SIGKILL); uspool->harakiri = 0; } uspool = uspool->next; } #endif #ifdef __linux__ #ifdef MADV_MERGEABLE if (uwsgi.linux_ksm > 0 && (uwsgi.master_cycles % uwsgi.linux_ksm) == 0) { uwsgi_linux_ksm_map(); } #endif #endif #ifdef UWSGI_UDP // check for cluster nodes master_check_cluster_nodes(); // reannounce myself every 10 cycles if (uwsgi.cluster && uwsgi.cluster_fd >= 0 && !uwsgi.cluster_nodes && (uwsgi.master_cycles % 10) == 0) { uwsgi_cluster_add_me(); } // resubscribe every 10 cycles by default if (( (uwsgi.subscriptions || uwsgi.subscriptions2) && ((uwsgi.master_cycles % uwsgi.subscribe_freq) == 0 || uwsgi.master_cycles == 1)) && !uwsgi.to_heaven && !uwsgi.to_hell && !uwsgi.workers[0].suspended) { uwsgi_subscribe_all(0, 0); } #endif if (uwsgi.cache_store && uwsgi.cache_filesize && uwsgi.cache_store_sync && ((uwsgi.master_cycles % uwsgi.cache_store_sync) == 0)) { if (msync(uwsgi.cache_items, uwsgi.cache_filesize, MS_ASYNC)) { uwsgi_error("msync()"); } } if (uwsgi.queue_store && uwsgi.queue_filesize && uwsgi.queue_store_sync && ((uwsgi.master_cycles % uwsgi.queue_store_sync) == 0)) { if (msync(uwsgi.queue_header, uwsgi.queue_filesize, MS_ASYNC)) { uwsgi_error("msync()"); } } // check touch_reload if (!uwsgi.to_heaven && !uwsgi.to_hell) { char *touched = uwsgi_check_touches(uwsgi.touch_reload); if (touched) { uwsgi_log("*** %s has been touched... grace them all !!! ***\n", touched); uwsgi_block_signal(SIGHUP); grace_them_all(0); uwsgi_unblock_signal(SIGHUP); } } continue; } // no one died if (diedpid <= 0) continue; // check for deadlocks first uwsgi_deadlock_check(diedpid); // reload gateways and daemons only on normal workflow (+outworld status) if (!uwsgi.to_heaven && !uwsgi.to_hell) { #ifdef UWSGI_SPOOLER /* reload the spooler */ struct uwsgi_spooler *uspool = uwsgi.spoolers; pid_found = 0; while (uspool) { if (uspool->pid > 0 && diedpid == uspool->pid) { uwsgi_log("OOOPS the spooler is no more...trying respawn...\n"); uspool->respawned++; uspool->pid = spooler_start(uspool); pid_found = 1; break; } uspool = uspool->next; } if (pid_found) continue; #endif pid_found = 0; for (i = 0; i < uwsgi.mules_cnt; i++) { if (uwsgi.mules[i].pid == diedpid) { uwsgi_log("OOOPS mule %d (pid: %d) crippled...trying respawn...\n", i + 1, uwsgi.mules[i].pid); uwsgi_mule(i + 1); pid_found = 1; break; } } if (pid_found) continue; /* reload the gateways */ pid_found = 0; for (i = 0; i < ushared->gateways_cnt; i++) { if (ushared->gateways[i].pid == diedpid) { gateway_respawn(i); pid_found = 1; break; } } if (pid_found) continue; /* reload the daemons */ pid_found = uwsgi_daemon_check_pid_reload(diedpid); if (pid_found) continue; } /* What happens here ? case 1) the diedpid is not a worker, report it and continue case 2) the diedpid is a worker and we are not in a reload procedure -> reload it case 3) the diedpid is a worker and we are in graceful reload -> uwsgi.ready_to_reload++ and continue case 3) the diedpid is a worker and we are in brutal reload -> uwsgi.ready_to_die++ and continue */ uwsgi.mywid = find_worker_id(diedpid); if (uwsgi.mywid <= 0) { // check spooler, mules, gateways and daemons #ifdef UWSGI_SPOOLER struct uwsgi_spooler *uspool = uwsgi.spoolers; while (uspool) { if (uspool->pid > 0 && diedpid == uspool->pid) { uwsgi_log("spooler (pid: %d) annihilated\n", (int) diedpid); goto next; } uspool = uspool->next; } #endif for (i = 0; i < uwsgi.mules_cnt; i++) { if (uwsgi.mules[i].pid == diedpid) { uwsgi_log("mule %d (pid: %d) annihilated\n", i + 1, (int) diedpid); goto next; } } for (i = 0; i < ushared->gateways_cnt; i++) { if (ushared->gateways[i].pid == diedpid) { uwsgi_log("gateway %d (%s, pid: %d) annihilated\n", i + 1, ushared->gateways[i].fullname, (int) diedpid); goto next; } } if (uwsgi_daemon_check_pid_death(diedpid)) goto next; if (WIFEXITED(waitpid_status)) { uwsgi_log("subprocess %d exited with code %d\n", (int) diedpid, WEXITSTATUS(waitpid_status)); } else if (WIFSIGNALED(waitpid_status)) { uwsgi_log("subprocess %d exited by signal %d\n", (int) diedpid, WTERMSIG(waitpid_status)); } else if (WIFSTOPPED(waitpid_status)) { uwsgi_log("subprocess %d stopped\n", (int) diedpid); } next: continue; } // ok a worker died... if (uwsgi.to_heaven) { uwsgi.ready_to_reload++; uwsgi.workers[uwsgi.mywid].pid = 0; // only to be safe :P uwsgi.workers[uwsgi.mywid].harakiri = 0; continue; } else if (uwsgi.to_hell) { uwsgi.ready_to_die++; uwsgi.workers[uwsgi.mywid].pid = 0; // only to be safe :P uwsgi.workers[uwsgi.mywid].harakiri = 0; continue; } else if (uwsgi.to_outworld) { uwsgi.lazy_respawned++; uwsgi.workers[uwsgi.mywid].destroy = 0; uwsgi.workers[uwsgi.mywid].pid = 0; // only to be safe :P uwsgi.workers[uwsgi.mywid].harakiri = 0; } if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_FAILED_APP_CODE) { uwsgi_log("OOPS ! failed loading app in worker %d (pid %d) :( trying again...\n", uwsgi.mywid, (int) diedpid); } else if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_DE_HIJACKED_CODE) { uwsgi_log("...restoring worker %d (pid: %d)...\n", uwsgi.mywid, (int) diedpid); } else if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_EXCEPTION_CODE) { uwsgi_log("... monitored exception detected, respawning worker %d (pid: %d)...\n", uwsgi.mywid, (int) diedpid); } else if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_QUIET_CODE) { // noop } else if (uwsgi.workers[uwsgi.mywid].manage_next_request) { if (WIFSIGNALED(waitpid_status)) { uwsgi_log("DAMN ! worker %d (pid: %d) died, killed by signal %d :( trying respawn ...\n", uwsgi.mywid, (int) diedpid, (int) WTERMSIG(waitpid_status)); } else { uwsgi_log("DAMN ! worker %d (pid: %d) died :( trying respawn ...\n", uwsgi.mywid, (int) diedpid); } } // manage_next_request is zero, but killed by signal... else if (WIFSIGNALED(waitpid_status)) { uwsgi_log("DAMN ! worker %d (pid: %d) MISTERIOUSLY killed by signal %d :( trying respawn ...\n", uwsgi.mywid, (int) diedpid, (int) WTERMSIG(waitpid_status)); } if (uwsgi.workers[uwsgi.mywid].cheaped == 1) { uwsgi.workers[uwsgi.mywid].pid = 0; uwsgi_log("uWSGI worker %d cheaped.\n", uwsgi.mywid); uwsgi.workers[uwsgi.mywid].harakiri = 0; continue; } gettimeofday(&last_respawn, NULL); if (last_respawn.tv_sec <= uwsgi.respawn_delta + check_interval) { last_respawn_rate++; if (last_respawn_rate > uwsgi.numproc) { if (uwsgi.forkbomb_delay > 0) { uwsgi_log("worker respawning too fast !!! i have to sleep a bit (%d seconds)...\n", uwsgi.forkbomb_delay); /* use --forkbomb-delay 0 to disable sleeping */ sleep(uwsgi.forkbomb_delay); } last_respawn_rate = 0; } } else { last_respawn_rate = 0; } gettimeofday(&last_respawn, NULL); uwsgi.respawn_delta = last_respawn.tv_sec; if (uwsgi_respawn_worker(uwsgi.mywid)) return 0; // end of the loop } // never here }
int main (int argc, char *argv[]) { int var = 1; /* The fork system call is used by a process to request that the kernel create a new process. After fork has been called a new child process exists. Both the parent and the child then keep executing from the point right after the call to fork. Thus, both the parent and the child process both get a return value from fork. The child process gets a return value of 0, and the parent process gets a return value equal to the process ID of the newly created child. */ int c1 = 0; c1 = fork (); if (c1 == 0) { /* we enter this block only if fork returns 0, which indicates that we are the child process */ printf ("Value of var from child = %d\n", var); ++var; // var is only incremented in the child process } else { // the parent process does not increment var; it sleeps instead int status; int retvalue = 0; while (retvalue != c1) { status = 0; retvalue = waitpid (c1, &status, 0); if (retvalue < 0) { char buffer[256]; strerror_r (errno, buffer, 256); printf ("error occured %s\n", buffer); break; } else { printf ("state of process %d changed - ", retvalue); if (WIFEXITED (status)) { printf ("exited, status=%d\n", WEXITSTATUS (status)); } else if (WIFSIGNALED (status)) { printf ("killed by signal %d\n", WTERMSIG (status)); } else if (WIFSTOPPED (status)) { printf ("stopped by signal %d\n", WSTOPSIG (status)); } else if (WIFCONTINUED (status)) { printf ("continued\n"); } } } } /* The line below will be executed twice: once from the child and once from the parent. Recall that the parent process and child process have separate address spaces; thus, because only the child incremented the value of var, only the child will print that the value of var is 2. */ printf ("From process %d, value of var is %d.\n", getpid (), var); return 0; }
int main(int argc, char *argv[]) { int ret; pthread_t th; pid_t chk; int status; char *ts = "[??:??:??]"; struct tm *now; time_t nw; /* check args */ if (argc < 3) { printf("\nUsage: \n"); printf(" $ %s n exe arglist\n", argv[0]); printf("\nWhere:\n"); printf(" n is the timeout duration in hours,\n"); printf(" exe is the stress test executable to monitor,\n"); printf (" arglist is the arguments to be passed to executable.\n\n"); return 2; } timeout = atoi(argv[1]); if (timeout < 1) { fprintf(stderr, "Invalid timeout value \"%s\". Timeout must be a positive integer.\n", argv[1]); return 2; } /* create the timer thread */ ret = pthread_create(&th, NULL, timer, NULL); if (ret != 0) { perror("Failed to create the timeout thread\n"); return 2; } /* Create the new process for the stress test */ child = fork(); if (child == (pid_t) - 1) { perror("Failed to create a new process"); exit(2); } /* The child process executes the test */ if (child == (pid_t) 0) { /* Execute the command */ ret = execvp(argv[2], &argv[2]); if (ret == -1) { /* Application was not launched */ perror("Unable to run child application"); return 2; } assert(0); perror("Should not see me"); return 2; } /* The parent: */ /* wait for the child process to terminate */ chk = waitpid(child, &status, 0); if (chk != child) { perror("Got the wrong process image status"); return 2; } /* Cancel the timer thread in case the process returned by itself */ (void)pthread_cancel(th); ret = pthread_join(th, NULL); if (ret != 0) { perror("Unable to join the timer thread"); return 2; } /* return */ nw = time(NULL); now = localtime(&nw); if (now == NULL) printf(ts); else printf("[%2.2d:%2.2d:%2.2d]", now->tm_hour, now->tm_min, now->tm_sec); if (!WIFEXITED(status)) { printf("The stress sample did not exit\n"); if (WIFSIGNALED(status)) { printf("It was killed with signal %i\n", WTERMSIG(status)); } else { printf("and it was not killed...\n"); } exit(1); } if (WEXITSTATUS(status) == 0) { printf("Test %s PASSED\n", argv[2]); } else { printf("Test %s: returned %d\n", argv[2], WEXITSTATUS(status)); } exit(WEXITSTATUS(status)); }
static void process_children(void) { int i; /* Looping var */ int status; /* Exit status of child */ int pid; /* Process ID of child */ cupsd_backend_t *backend; /* Current backend */ const char *name; /* Name of process */ /* * Reset the dead_children flag... */ dead_children = 0; /* * Collect the exit status of some children... */ #ifdef HAVE_WAITPID while ((pid = waitpid(-1, &status, WNOHANG)) > 0) #elif defined(HAVE_WAIT3) while ((pid = wait3(&status, WNOHANG, NULL)) > 0) #else if ((pid = wait(&status)) > 0) #endif /* HAVE_WAITPID */ { if (status == SIGTERM) status = 0; for (i = num_backends, backend = backends; i > 0; i --, backend ++) if (backend->pid == pid) break; if (i > 0) { name = backend->name; backend->pid = 0; backend->status = status; active_backends --; } else name = "Unknown"; if (status) { if (WIFEXITED(status)) fprintf(stderr, "ERROR: [cups-deviced] PID %d (%s) stopped with status %d!\n", pid, name, WEXITSTATUS(status)); else fprintf(stderr, "ERROR: [cups-deviced] PID %d (%s) crashed on signal %d!\n", pid, name, WTERMSIG(status)); } else fprintf(stderr, "DEBUG: [cups-deviced] PID %d (%s) exited with no errors.\n", pid, name); } }
/* * Collect the child's exit status. The initiating thread must do this on uClibc. * Return zero if the exit status is successfully reaped. Return -1 if an error * and return > 0 if process still running. */ int mprReapCmd(MprCmd *cmd, int timeout) { MprTime mark; mprAssert(cmd->pid); if (timeout < 0) { timeout = MAXINT; } mark = mprGetTime(cmd); while (cmd->pid) { #if BLD_UNIX_LIKE int status, waitrc; status = 0; if ((waitrc = waitpid(cmd->pid, &status, WNOHANG | __WALL)) < 0) { mprAssert(0); mprLog(cmd, 0, "waitpid failed for pid %d, errno %d", cmd->pid, errno); return MPR_ERR_CANT_READ; } else if (waitrc == cmd->pid) { if (!WIFSTOPPED(status)) { if (WIFEXITED(status)) { cmd->status = WEXITSTATUS(status); } else if (WIFSIGNALED(status)) { cmd->status = WTERMSIG(status); } cmd->pid = 0; } break; } else { mprAssert(waitrc == 0); } #endif #if VXWORKS /* * The command exit status (cmd->status) is set in cmdTaskEntry */ if (semTake(cmd->exitCond, MPR_TIMEOUT_STOP_TASK) != OK) { mprError(cmd, "cmd: child %s did not exit, errno %d", cmd->program); return MPR_ERR_CANT_CREATE; } semDelete(cmd->exitCond); cmd->exitCond = 0; cmd->pid = 0; #endif #if BLD_WIN_LIKE int status, rc; if ((rc = WaitForSingleObject(cmd->process, 10)) != WAIT_OBJECT_0) { if (rc == WAIT_TIMEOUT) { return -MPR_ERR_TIMEOUT; } mprLog(cmd, 6, "cmd: WaitForSingleObject no child to reap rc %d, %d", rc, GetLastError()); return MPR_ERR_CANT_READ; } if (GetExitCodeProcess(cmd->process, (ulong*) &status) == 0) { mprLog(cmd, 7, "cmd: GetExitProcess error"); return MPR_ERR_CANT_READ; } if (status != STILL_ACTIVE) { cmd->status = status; CloseHandle(cmd->process); CloseHandle(cmd->thread); cmd->process = 0; cmd->pid = 0; break; } #endif if (mprGetElapsedTime(cmd, mark) > timeout) { break; } /* Prevent busy waiting */ mprSleep(cmd, 10); } return (cmd->pid == 0) ? 0 : 1; }
static int openInputDevice(lua_State *L) { const char* inputdevice = luaL_checkstring(L, 1); #ifndef EMULATE_READER int fd; int childpid; fd = findFreeFdSlot(); if(fd == -1) { return luaL_error(L, "no free slot for new input device <%s>", inputdevice); } if(!strcmp("fake_events", inputdevice)) { /* special case: the power slider */ int pipefd[2]; pipe(pipefd); if((childpid = fork()) == -1) { return luaL_error(L, "cannot fork() slider event listener"); } if(childpid == 0) { // We send a SIGTERM to this child on exit, trap it to kill lipc properly. signal(SIGTERM, slider_handler); FILE *fp; char std_out[256]; int status; struct input_event ev; __u16 key_code = 10000; close(pipefd[0]); ev.type = EV_KEY; ev.code = key_code; ev.value = 1; /* listen power slider events (listen for ever for multiple events) */ char *argv[] = {"lipc-wait-event", "-m", "-s", "0", "com.lab126.powerd", "goingToScreenSaver,outOfScreenSaver,charging,notCharging", (char *) NULL}; /* @TODO 07.06 2012 (houqp) * plugin and out event can only be watched by: lipc-wait-event com.lab126.hal usbPlugOut,usbPlugIn */ fp = popen_noshell("lipc-wait-event", (const char * const *)argv, "r", &pclose_arg, 0); if (!fp) { err(EXIT_FAILURE, "popen_noshell()"); } /* Flush to get rid of buffering issues? */ fflush(fp); while(fgets(std_out, sizeof(std_out)-1, fp)) { if(std_out[0] == 'g') { ev.code = CODE_IN_SAVER; } else if(std_out[0] == 'o') { ev.code = CODE_OUT_SAVER; } else if((std_out[0] == 'u') && (std_out[7] == 'I')) { ev.code = CODE_USB_PLUG_IN; } else if((std_out[0] == 'u') && (std_out[7] == 'O')) { ev.code = CODE_USB_PLUG_OUT; } else if(std_out[0] == 'c') { ev.code = CODE_CHARGING; } else if(std_out[0] == 'n') { ev.code = CODE_NOT_CHARGING; } else { printf("Unrecognized event.\n"); } /* fill event struct */ gettimeofday(&ev.time, NULL); /* generate event */ if(write(pipefd[1], &ev, sizeof(struct input_event)) == -1) { printf("Failed to generate event.\n"); } } status = pclose_noshell(&pclose_arg); if (status == -1) { err(EXIT_FAILURE, "pclose_noshell()"); } else { if (WIFEXITED(status)) { printf("lipc-wait-event exited normally with status: %d\n", WEXITSTATUS(status)); } else if (WIFSIGNALED(status)) { printf("lipc-wait-event was killed by signal %d\n", WTERMSIG(status)); } else if (WIFSTOPPED(status)) { printf("lipc-wait-event was stopped by signal %d\n", WSTOPSIG(status)); } else if (WIFCONTINUED(status)) { printf("lipc-wait-event continued\n"); } } // We're done, go away :). _exit(EXIT_SUCCESS); } else { close(pipefd[1]); inputfds[fd] = pipefd[0]; slider_pid = childpid; } } else { inputfds[fd] = open(inputdevice, O_RDONLY | O_NONBLOCK, 0); if(inputfds[fd] != -1) { ioctl(inputfds[fd], EVIOCGRAB, 1); return 0; } else { return luaL_error(L, "error opening input device <%s>: %d", inputdevice, errno); } } #else if(SDL_Init(SDL_INIT_VIDEO) < 0) { return luaL_error(L, "cannot initialize SDL."); } SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL); /* we only use inputfds[0] in emu mode, because we only have one * fake device so far. */ inputfds[0] = open(inputdevice, O_RDWR | O_NONBLOCK); if (inputfds < 0) { return luaL_error(L, "error opening input device <%s>: %d", inputdevice, errno); } #endif return 0; }