//Function for executing all the basic shell commands void execs(char *arr[],int rlflag,int rgflag) { int sin=dup(STDIN_FILENO); int sout=dup(STDOUT_FILENO); pp=fork(); if(flag==0) { if(pp<0) { perror("Error"); exit(0); } else if (pp==0) { if(rlflag==1) { FILE *fp=fopen(in1,"r"); dup2(fileno(fp),0); fclose(fp); } if(rgflag==1) { FILE *fp=fopen(out1,"w+"); dup2(fileno(fp),1); fclose(fp); } int val=execvp(arr[0],arr); if(val<0) { perror("Command not found"); exit(0); } } else { int s; waitpid(pp,&s,WUNTRACED); if(WIFSTOPPED(s)) { strcpy(procs[counters].name,arr[0]); procs[counters].pid=pp; procs[counters++].status=1; } } } else if (flag==1) { if(pp<0) { perror("Error"); exit(0); } else if (pp==0) { if(rlflag==1) { FILE *fp=fopen(in1,"r"); dup2(fileno(fp),0); } if(rgflag==1) { FILE *fp=fopen(out1,"w+"); dup2(fileno(fp),1); } int val=execvp(arr[0],arr); if(val<0) { perror("Command Not Found"); exit(0); } } else { strcpy(procs[counters].name,arr[0]); if((strcmp(arr[0],"gedit")==0||strcmp(arr[0],"emacs")==0)&&arr[1]!=NULL) strcpy(procs[counters].name2,arr[1]); procs[counters].pid=pp; procs[counters++].status=1; } } dup2(sout,1); dup2(sin,0); close(sout); close(sin); }
static void summarize (FILE *fp, const char *fmt, char **command, resource_t *resp) { unsigned long r; /* Elapsed real milliseconds. */ unsigned long v; /* Elapsed virtual (CPU) milliseconds. */ if (WIFSTOPPED (resp->waitstatus)) fprintf (fp, "Command stopped by signal %d\n", WSTOPSIG (resp->waitstatus)); else if (WIFSIGNALED (resp->waitstatus)) fprintf (fp, "Command terminated by signal %d\n", WTERMSIG (resp->waitstatus)); else if (WIFEXITED (resp->waitstatus) && WEXITSTATUS (resp->waitstatus)) fprintf (fp, "Command exited with non-zero status %d\n", WEXITSTATUS (resp->waitstatus)); /* Convert all times to milliseconds. Occasionally, one of these values comes out as zero. Dividing by zero causes problems, so we first check the time value. If it is zero, then we take `evasive action' instead of calculating a value. */ r = resp->elapsed.tv_sec * 1000 + resp->elapsed.tv_usec / 1000; v = resp->ru.ru_utime.tv_sec * 1000 + resp->ru.ru_utime.TV_MSEC + resp->ru.ru_stime.tv_sec * 1000 + resp->ru.ru_stime.TV_MSEC; while (*fmt) { switch (*fmt) { case '%': switch (*++fmt) { case '%': /* Literal '%'. */ putc ('%', fp); break; case 'C': /* The command that got timed. */ fprintargv (fp, command, " "); break; case 'D': /* Average unshared data size. */ fprintf (fp, "%lu", MSEC_TO_TICKS (v) == 0 ? 0 : ptok ((UL) resp->ru.ru_idrss) / MSEC_TO_TICKS (v) + ptok ((UL) resp->ru.ru_isrss) / MSEC_TO_TICKS (v)); break; case 'E': /* Elapsed real (wall clock) time. */ if (resp->elapsed.tv_sec >= 3600) /* One hour -> h:m:s. */ fprintf (fp, "%ldh %ldm %02lds", resp->elapsed.tv_sec / 3600, (resp->elapsed.tv_sec % 3600) / 60, resp->elapsed.tv_sec % 60); else fprintf (fp, "%ldm %ld.%02lds", /* -> m:s. */ resp->elapsed.tv_sec / 60, resp->elapsed.tv_sec % 60, resp->elapsed.tv_usec / 10000); break; case 'F': /* Major page faults. */ fprintf (fp, "%ld", resp->ru.ru_majflt); break; case 'I': /* Inputs. */ fprintf (fp, "%ld", resp->ru.ru_inblock); break; case 'K': /* Average mem usage == data+stack+text. */ fprintf (fp, "%lu", MSEC_TO_TICKS (v) == 0 ? 0 : ptok ((UL) resp->ru.ru_idrss) / MSEC_TO_TICKS (v) + ptok ((UL) resp->ru.ru_isrss) / MSEC_TO_TICKS (v) + ptok ((UL) resp->ru.ru_ixrss) / MSEC_TO_TICKS (v)); break; case 'M': /* Maximum resident set size. */ fprintf (fp, "%lu", ptok ((UL) resp->ru.ru_maxrss)); break; case 'O': /* Outputs. */ fprintf (fp, "%ld", resp->ru.ru_oublock); break; case 'P': /* Percent of CPU this job got. */ /* % cpu is (total cpu time)/(elapsed time). */ if (r > 0) fprintf (fp, "%lu%%", (v * 100 / r)); else fprintf (fp, "?%%"); break; case 'R': /* Minor page faults (reclaims). */ fprintf (fp, "%ld", resp->ru.ru_minflt); break; case 'S': /* System time. */ fprintf (fp, "%ld.%02ld", resp->ru.ru_stime.tv_sec, resp->ru.ru_stime.TV_MSEC / 10); break; case 'T': /* System time. */ if (resp->ru.ru_stime.tv_sec >= 3600) /* One hour -> h:m:s. */ fprintf (fp, "%ldh %ldm %02lds", resp->ru.ru_stime.tv_sec / 3600, (resp->ru.ru_stime.tv_sec % 3600) / 60, resp->ru.ru_stime.tv_sec % 60); else fprintf (fp, "%ldm %ld.%02lds", /* -> m:s. */ resp->ru.ru_stime.tv_sec / 60, resp->ru.ru_stime.tv_sec % 60, resp->ru.ru_stime.tv_usec / 10000); break; case 'U': /* User time. */ fprintf (fp, "%ld.%02ld", resp->ru.ru_utime.tv_sec, resp->ru.ru_utime.TV_MSEC / 10); break; case 'u': /* User time. */ if (resp->ru.ru_utime.tv_sec >= 3600) /* One hour -> h:m:s. */ fprintf (fp, "%ldh %ldm %02lds", resp->ru.ru_utime.tv_sec / 3600, (resp->ru.ru_utime.tv_sec % 3600) / 60, resp->ru.ru_utime.tv_sec % 60); else fprintf (fp, "%ldm %ld.%02lds", /* -> m:s. */ resp->ru.ru_utime.tv_sec / 60, resp->ru.ru_utime.tv_sec % 60, resp->ru.ru_utime.tv_usec / 10000); break; case 'W': /* Times swapped out. */ fprintf (fp, "%ld", resp->ru.ru_nswap); break; case 'X': /* Average shared text size. */ fprintf (fp, "%lu", MSEC_TO_TICKS (v) == 0 ? 0 : ptok ((UL) resp->ru.ru_ixrss) / MSEC_TO_TICKS (v)); break; case 'Z': /* Page size. */ fprintf (fp, "%d", getpagesize ()); break; case 'c': /* Involuntary context switches. */ fprintf (fp, "%ld", resp->ru.ru_nivcsw); break; case 'e': /* Elapsed real time in seconds. */ fprintf (fp, "%ld.%02ld", resp->elapsed.tv_sec, resp->elapsed.tv_usec / 10000); break; case 'k': /* Signals delivered. */ fprintf (fp, "%ld", resp->ru.ru_nsignals); break; case 'p': /* Average stack segment. */ fprintf (fp, "%lu", MSEC_TO_TICKS (v) == 0 ? 0 : ptok ((UL) resp->ru.ru_isrss) / MSEC_TO_TICKS (v)); break; case 'r': /* Incoming socket messages received. */ fprintf (fp, "%ld", resp->ru.ru_msgrcv); break; case 's': /* Outgoing socket messages sent. */ fprintf (fp, "%ld", resp->ru.ru_msgsnd); break; case 't': /* Average resident set size. */ fprintf (fp, "%lu", MSEC_TO_TICKS (v) == 0 ? 0 : ptok ((UL) resp->ru.ru_idrss) / MSEC_TO_TICKS (v)); break; case 'w': /* Voluntary context switches. */ fprintf (fp, "%ld", resp->ru.ru_nvcsw); break; case 'x': /* Exit status. */ fprintf (fp, "%d", WEXITSTATUS (resp->waitstatus)); break; case '\0': putc ('?', fp); return; default: putc ('?', fp); putc (*fmt, fp); } ++fmt; break; case '\\': /* Format escape. */ switch (*++fmt) { case 't': putc ('\t', fp); break; case 'n': putc ('\n', fp); break; case '\\': putc ('\\', fp); break; default: putc ('?', fp); putc ('\\', fp); putc (*fmt, fp); } ++fmt; break; default: putc (*fmt++, fp); } if (ferror (fp)) bb_error_msg_and_die("write error"); } putc ('\n', fp); if (ferror (fp)) bb_error_msg_and_die("write error"); }
int printYAMLJobInfo(FILE *out, int indent, const char* tag, const JobInfo* job) { /* purpose: format the job information into the given stream as YAML. * paramtr: out (IO): the stream * indent (IN): indentation level * tag (IN): name to use for element tags. * job (IN): job info to print. * returns: number of characters put into buffer (buffer length) */ /* sanity check */ if (!job->isValid) { return 0; } /* start tag with indentation */ fprintf(out, "%*s%s:\n", indent, "", tag); fprintf(out, "%*s start: %s\n", indent, "", fmtisodate(job->start.tv_sec, job->start.tv_usec)); fprintf(out, "%*s duration: %.3f\n", indent, "", doubletime(job->finish) - doubletime(job->start)); /* optional attribute: application process id */ if (job->child != 0) { fprintf(out, "%*s pid: %d\n", indent, "", job->child); } /* <usage> */ printYAMLUseInfo(out, indent+2, "usage", &job->use); int status = (int) job->status; /* <status>: open tag */ fprintf(out, "%*sstatus:\n%*sraw: %d\n", indent+2, "", indent+4, "", status); /* <status>: cases of completion */ if (status < 0) { /* <failure> */ fprintf(out, "%*sfailure_error: %d %s%s\n", indent+4, "", job->saverr, job->prefix && job->prefix[0] ? job->prefix : "", strerror(job->saverr)); } else if (WIFEXITED(status)) { fprintf(out, "%*sregular_exitcode: %d\n", indent+4, "", WEXITSTATUS(status)); } else if (WIFSIGNALED(status)) { /* result = 128 + WTERMSIG(status); */ fprintf(out, "%*ssignalled_signal: %u\n", indent+4, "", WTERMSIG(status)); fprintf(out, "%*ssingalled_name: %s\n", indent+4, "", sys_siglist[WTERMSIG(status)]); #ifdef WCOREDUMP fprintf(out, "%*scorefile: %s\n", indent+4, "", WCOREDUMP(status) ? "true" : "false"); #endif } else if (WIFSTOPPED(status)) { fprintf(out, "%*ssuspended_signal: %u\n", indent+4, "", WSTOPSIG(status)); fprintf(out, "%*ssuspended_name: %s\n", indent+4, "", sys_siglist[WSTOPSIG(status)]); } /* FIXME: else? */ /* <executable> */ printYAMLStatInfo(out, indent+2, "executable", &job->executable, 1, 0, 1); /* alternative 1: new-style <argument-vector> */ fprintf(out, "%*sargument_vector:\n", indent+2, ""); if (job->argc > 1) { /* content are the CLI args */ int i; for (i=1; i<job->argc; ++i) { fprintf(out, "%*s- %s\n", indent+4, "", job->argv[i]); } } /* <proc>s */ printYAMLProcInfo(out, indent+2, job->children); return 0; }
static void handle_child(pid_t childpid, int childstatus) { unsigned int i; int slot; switch (childpid) { case 0: //debugf("Nothing changed. children:%d\n", shm->running_childs); break; case -1: if (shm->exit_reason != STILL_RUNNING) return; if (errno == ECHILD) { debugf("All children exited!\n"); for_each_pidslot(i) { if (shm->pids[i] != EMPTY_PIDSLOT) { if (pid_alive(shm->pids[i]) == -1) { debugf("Removing %d from pidmap\n", shm->pids[i]); shm->pids[i] = EMPTY_PIDSLOT; shm->running_childs--; } else { debugf("%d looks still alive! ignoring.\n", shm->pids[i]); } } } break; } output(0, "error! (%s)\n", strerror(errno)); break; default: debugf("Something happened to pid %d\n", childpid); if (WIFEXITED(childstatus)) { slot = find_pid_slot(childpid); if (slot == PIDSLOT_NOT_FOUND) { /* If we reaped it, it wouldn't show up, so check that. */ if (shm->last_reaped != childpid) { outputerr("## Couldn't find pid slot for %d\n", childpid); shm->exit_reason = EXIT_LOST_PID_SLOT; dump_pid_slots(); } } else { debugf("Child %d exited after %ld syscalls.\n", childpid, shm->child_syscall_count[slot]); reap_child(childpid); } break; } else if (WIFSIGNALED(childstatus)) { switch (WTERMSIG(childstatus)) { case SIGALRM: debugf("got a alarm signal from pid %d\n", childpid); break; case SIGFPE: case SIGSEGV: case SIGKILL: case SIGPIPE: case SIGABRT: debugf("got a signal from pid %d (%s)\n", childpid, strsignal(WTERMSIG(childstatus))); reap_child(childpid); break; default: debugf("** Child got an unhandled signal (%d)\n", WTERMSIG(childstatus)); break; } break; } else if (WIFSTOPPED(childstatus)) { switch (WSTOPSIG(childstatus)) { case SIGALRM: debugf("got an alarm signal from pid %d\n", childpid); break; case SIGSTOP: debugf("Sending PTRACE_DETACH (and then KILL)\n"); //ptrace(PTRACE_DETACH, childpid, NULL, NULL); kill(childpid, SIGKILL); reap_child(childpid); break; case SIGFPE: case SIGSEGV: case SIGKILL: case SIGPIPE: case SIGABRT: debugf("Child %d was stopped by %s\n", childpid, strsignal(WTERMSIG(childstatus))); reap_child(childpid); break; default: debugf("Child %d was stopped by unhandled signal (%s).\n", childpid, strsignal(WSTOPSIG(childstatus))); break; } break; } else if (WIFCONTINUED(childstatus)) { break; } else { output(0, "erk, wtf\n"); } }
/* exec another program, putting result in output. * This is simple version of full run_phase. */ void run_simple_program (char *name, char **argv, char *output) { int forkpid; int fdout; int waitpid; int waitstatus; int termsig; /* fork a process */ forkpid = fork(); if (forkpid == -1) { error("no more processes"); cleanup (); do_exit (RC_SYSTEM_ERROR); /* NOTREACHED */ } if (forkpid == 0) { /* child */ if ((fdout = creat (output, 0666)) == -1) { error ("cannot create output file %s", output); cleanup (); do_exit (RC_SYSTEM_ERROR); /* NOTREACHED */ } dup2 (fdout, fileno(stdout)); my_execv(name, argv); } else { /* parent */ int procid; /* id of the /proc file */ while ((waitpid = wait (&waitstatus)) != forkpid) { if (waitpid == -1) { error("bad return from wait"); cleanup(); do_exit(RC_SYSTEM_ERROR); /* NOTREACHED */ } } if (WIFSTOPPED(waitstatus)) { termsig = WSTOPSIG(waitstatus); error("STOPPED signal received from %s", name); cleanup(); do_exit(RC_SYSTEM_ERROR); /* NOTREACHED */ } else if (WIFEXITED(waitstatus)) { int status = WEXITSTATUS(waitstatus); if (status != RC_OKAY) { /* internal error */ /* most internal errors use exit code of 1 */ internal_error("%s returned non-zero status %d", name, status); } return; } else if(WIFSIGNALED(waitstatus)){ termsig = WTERMSIG(waitstatus); switch (termsig) { case SIGHUP: case SIGINT: case SIGQUIT: case SIGKILL: case SIGTERM: error("%s died due to signal %d", name, termsig); break; default: internal_error("%s died due to signal %d", name, termsig); break; } #ifndef __CYGWIN__ if(waitstatus & WCOREFLAG) { error("core dumped"); } #endif if (termsig == SIGKILL) { error("Probably caused by running out of swap space -- check %s", LOGFILE); } cleanup(); do_exit(RC_SYSTEM_ERROR); } else { /* cannot happen, I think! */ internal_error("driver exec'ing is confused"); return; } } }
void userspace(union uml_pt_regs *regs) { int err, status, op, pt_syscall_parm, pid = userspace_pid[0]; int local_using_sysemu; /*To prevent races if using_sysemu changes under us.*/ restore_registers(regs); local_using_sysemu = get_using_sysemu(); pt_syscall_parm = local_using_sysemu ? PTRACE_SYSEMU : PTRACE_SYSCALL; err = ptrace(pt_syscall_parm, pid, 0, 0); if(err) panic("userspace - PTRACE_%s failed, errno = %d\n", local_using_sysemu ? "SYSEMU" : "SYSCALL", errno); while(1){ CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED)); if(err < 0) panic("userspace - waitpid failed, errno = %d\n", errno); regs->skas.is_user = 1; save_registers(regs); if(WIFSTOPPED(status)){ switch(WSTOPSIG(status)){ case SIGSEGV: handle_segv(pid); break; case SIGTRAP: handle_trap(pid, regs, local_using_sysemu); break; case SIGIO: case SIGVTALRM: case SIGILL: case SIGBUS: case SIGFPE: case SIGWINCH: user_signal(WSTOPSIG(status), regs); break; default: printk("userspace - child stopped with signal " "%d\n", WSTOPSIG(status)); } interrupt_end(); } restore_registers(regs); /*Now we ended the syscall, so re-read local_using_sysemu.*/ local_using_sysemu = get_using_sysemu(); pt_syscall_parm = local_using_sysemu ? PTRACE_SYSEMU : PTRACE_SYSCALL; op = singlestepping(NULL) ? PTRACE_SINGLESTEP : pt_syscall_parm; err = ptrace(op, pid, 0, 0); if(err) panic("userspace - PTRACE_%s failed, " "errno = %d\n", local_using_sysemu ? "SYSEMU" : "SYSCALL", errno); } }
static void parent(pid_t child_pid) { int status; bool exec_done = 0; while (1) { /* Wait for child status to change: */ wait(&status); if (WIFEXITED(status)) { // printf("Child exit with status %d\n", WEXITSTATUS(status)); exit(WEXITSTATUS(status)); } if (WIFSIGNALED(status)) { fprintf(stderr, "Child exit due to signal %d\n", WTERMSIG(status)); exit(0); } if (!WIFSTOPPED(status)) { fprintf(stderr, "wait() returned unhandled status 0x%x\n", status); exit(0); } if (WSTOPSIG(status) == SIGTRAP) { /* Note that there are *three* reasons why the child might stop * with SIGTRAP: * 1) syscall entry * 2) syscall exit * 3) child calls exec */ siginfo_t info; ptrace(PTRACE_GETSIGINFO, child_pid, 0, &info); if (info.si_code != SIGTRAP) { if (exec_done) { fprintf(stderr, "CHILD PERFORMED EXEC\n"); kill(child_pid, SIGKILL); abort(); } else { exec_done = 1; } } else { #if 0 sc_number = ptrace(PTRACE_PEEKUSER, child_pid, SC_NUMBER, NULL); // sc_retcode = ptrace(PTRACE_PEEKUSER, child_pid, SC_RETCODE, NULL); // printf("SIGTRAP: syscall %ld, rc = %ld\n", sc_number, sc_retcode); if (sc_number<0 || sc_number>512 || !is_allowed_syscall[sc_number]) { fprintf(stderr, "BLOCKED SYSCALL %ld\n", sc_number); kill(child_pid, SIGKILL); abort(); } #endif } } else if (WSTOPSIG(status) == 31) { long sc_number = ptrace(PTRACE_PEEKUSER, child_pid, SC_NUMBER, NULL); fprintf(stderr, "BLOCKED SYSCALL %ld\n", sc_number); kill(child_pid, SIGKILL); exit(1); } else { if (WSTOPSIG(status) != 19) { fprintf(stderr, "Child stopped due to signal %d\n", WSTOPSIG(status)); kill(child_pid, SIGKILL); exit(1); } } // fflush(stdout); /* Resume child, requesting that it stops again on syscall enter/exit * (in addition to any other reason why it might stop): */ // ptrace(PTRACE_SYSCALL, child_pid, NULL, NULL); ptrace(PTRACE_CONT, child_pid, NULL, NULL); } }
int VectorMatch::computVectorMatch(std::string cmpFile, int k, int p,std::chrono::duration<double>* time_elapse){ //get all that shared mem stuff set up int shmId; // ID of shared memory segment key_t shmKey = 123460; // key to pass to shmget(), key_t is an IPC key type defined in sys/types int shmFlag = IPC_CREAT | 0666; // Flag to create with rw permissions pid_t pid; unsigned long * sharedIndexPtr = NULL; //store the pids for the procs std::set<pid_t> minvan; //start and end for times the proc work std::chrono::time_point<std::chrono::system_clock> start, end; long cmpVecPos = 0; try{ cmpVecPos = nameMap->at(cmpFile); } catch(...){ std::cerr<<"File not found in the database for comapring\n"; return 0; } //get the number of lines each proc gets to process int divNum = nameMap->size() / p; //create the shared memeory if ((shmId = shmget(shmKey, (p * k * sizeof(shmKeyPair)) , shmFlag)) < 0){ std::cerr << "Init: Failed to initialize shared memory (" << shmId << ")" << std::endl; return -1; } shmKeyPair* shm; //get the shared memory in the right address space if ((shm = (shmKeyPair *)shmat(shmId, NULL, 0)) == (shmKeyPair *) -1){ std::cerr << "Init: Failed to attach shared memory (" << shmId << ")" << std::endl; return -1; } start = std::chrono::system_clock::now(); //this loops through and forks enough procs to process each file // 1 proc per file for(int i = 0; i < p; i++){ pid = fork(); if ( pid < 0 ){ std::cerr << "Could not fork!!! ("<< pid <<")" << std::endl; return -1; } //this is the child taking over else if (pid == 0){ long lineStatus = 0; int procNum = i; //store the results of the vector std::map<float,int> results; int topBound = ((procNum * divNum) + divNum); if(i == (p-1)){ topBound += nameMap->size() % p; } //get the distances and store them into a map that auto sorts by distance for(long j = procNum * divNum; j < topBound -1; j++){ //add the distance to the results map results.insert(std::pair<float,long>(findDist(cmpVecPos,j),j*lineLength)); } //add the results to the proper segment of the shared memory int count = procNum * k; int kcount = 0; for(auto& pair : results){ if(kcount >= k){ break; } shm[count].dist = pair.first; shm[count].lineNum = pair.second; count++; kcount++; } //not usre if this is going to work but lets try //zero out the contents for(;count <= ((procNum*k)+k); count++){ shm[count].dist = FLT_MAX; } exit(1); } //parent else{ minvan.insert(pid); } } //for making sure the chilren exite good #if 0 int status; // catch the status of the child do // in reality, mulptiple signals or exit status could come from the child { pid_t w = waitpid(pid, &status, WUNTRACED | WCONTINUED); if (w == -1) { std::cerr << "Error waiting for child process ("<< pid <<")" << std::endl; break; } if (WIFEXITED(status)) { if (status > 0) { std::cerr << "Child process ("<< pid <<") exited with non-zero status of " << WEXITSTATUS(status) << std::endl; continue; } else { std::cout << "Child process ("<< pid <<") exited with status of " << WEXITSTATUS(status) << std::endl; continue; } } else if (WIFSIGNALED(status)) { std::cout << "Child process ("<< pid <<") killed by signal (" << WTERMSIG(status) << ")" << std::endl; continue; } else if (WIFSTOPPED(status)) { std::cout << "Child process ("<< pid <<") stopped by signal (" << WSTOPSIG(status) << ")" << std::endl; continue; } else if (WIFCONTINUED(status)) { std::cout << "Child process ("<< pid <<") continued" << std::endl; continue; } } while (!WIFEXITED(status) && !WIFSIGNALED(status)); #endif int status; pid_t testingProc = 0; //wait for all the child procs to finish while(!minvan.empty()){ //probably not enough checks for the procs waiting but // i'll come back later and fix it do{ testingProc = wait(&status); }while (!WIFEXITED(status) && !WIFSIGNALED(status)); minvan.erase(testingProc); } //store the final results with line numbers std::vector<shmKeyPair> finalResultsNum(shm,shm+(k*p)); //hold the final filname matches std::vector<nameKeyPair> finalResultsName(k); //sort the final results std::sort(finalResultsNum.begin(),finalResultsNum.end(),shmKeyPairSort); //cut them off at the knees finalResultsNum.resize(k); int indexer = 0; for(auto elem : finalResultsNum){ // std::cout<<elem.lineNum<<" "; finalResultsName.push_back(nameKeyPair()); finalResultsName.at(indexer).filename = (*lineNumMap).at(elem.lineNum); finalResultsName.at(indexer).dist = elem.dist; indexer++; } //final cut off at the knees finalResultsName.resize(k); end = std::chrono::system_clock::now(); //get the output out to that csv, yea output_vector_to_file("results.csv",&finalResultsName); *time_elapse = end - start; std::cout<<"Time for parent processing: "<<(*time_elapse).count()<<std::endl; //delete the shrared mem, that stuff is scary //but its actually working great this time around if ((shmctl(shmId,IPC_RMID,0))==-1){ std::cerr<<"shared mem couldn't be deleted"<<std::endl; return -1; } return 1; }
ATF_TC_BODY(wait6_stop_and_go, tc) { siginfo_t si; struct wrusage wru; int st; pid_t pid; static const struct rlimit rl = { 0, 0 }; ATF_REQUIRE(setrlimit(RLIMIT_CORE, &rl) == 0); switch (pid = fork()) { case 0: sleep(100); /*FALLTHROUGH*/ case -1: ATF_REQUIRE(pid > 0); default: ATF_REQUIRE(kill(pid, SIGSTOP) == 0); ATF_REQUIRE(wait6(P_PID, pid, &st, WSTOPPED, &wru, &si) == pid); ATF_REQUIRE(!WIFEXITED(st)); ATF_REQUIRE(!WIFSIGNALED(st)); ATF_REQUIRE(WIFSTOPPED(st) && WSTOPSIG(st) == SIGSTOP); ATF_REQUIRE(!WIFCONTINUED(st)); ATF_REQUIRE(si.si_status == SIGSTOP); ATF_REQUIRE(si.si_pid == pid); ATF_REQUIRE(si.si_uid == getuid()); ATF_REQUIRE(si.si_code == CLD_STOPPED); #ifdef __NetBSD__ printf("user: %ju system: %ju\n", (uintmax_t)si.si_utime, (uintmax_t)si.si_utime); #endif ATF_REQUIRE(kill(pid, SIGCONT) == 0); ATF_REQUIRE(wait6(P_PID, pid, &st, WCONTINUED, &wru, &si) == pid); ATF_REQUIRE(!WIFEXITED(st)); ATF_REQUIRE(!WIFSIGNALED(st)); ATF_REQUIRE(WIFCONTINUED(st)); ATF_REQUIRE(!WIFSTOPPED(st)); ATF_REQUIRE(si.si_status == SIGCONT); ATF_REQUIRE(si.si_pid == pid); ATF_REQUIRE(si.si_uid == getuid()); ATF_REQUIRE(si.si_code == CLD_CONTINUED); #ifdef __NetBSD__ printf("user: %ju system: %ju\n", (uintmax_t)si.si_utime, (uintmax_t)si.si_utime); #endif ATF_REQUIRE(kill(pid, SIGQUIT) == 0); ATF_REQUIRE(wait6(P_PID, pid, &st, WEXITED, &wru, &si) == pid); ATF_REQUIRE(!WIFEXITED(st)); ATF_REQUIRE(WIFSIGNALED(st) && WTERMSIG(st) == SIGQUIT); ATF_REQUIRE(!WIFSTOPPED(st)); ATF_REQUIRE(!WIFCONTINUED(st)); ATF_REQUIRE(si.si_status == SIGQUIT); ATF_REQUIRE(si.si_pid == pid); ATF_REQUIRE(si.si_uid == getuid()); ATF_REQUIRE(si.si_code == CLD_KILLED); #ifdef __NetBSD__ printf("user: %ju system: %ju\n", (uintmax_t)si.si_utime, (uintmax_t)si.si_utime); #endif break; } }
int main(int argc, char *argv[]) { int tdcount, tlimit, mlimit; char exename[1024], inputfile[1024]; struct rlimit r; if (argc < 6) { printf("Usage: [id] [probid] [input] [time limit] [memory limit]\n"); exit(RET_SE); } tlimit = atoi(argv[4]); mlimit = atoi(argv[5]); sprintf(exename, "./%s", argv[1]); strcpy(inputfile, argv[3]); if ((pid = fork()) == 0) { freopen("input.txt", "r", stdin); chdir("sandbox"); chroot("."); freopen("output.txt", "w", stdout); setregid(99, 99); setreuid(99, 99); ptrace(PTRACE_TRACEME, 0, NULL, NULL); execl(exename, exename, NULL); exit(0); } signal(SIGALRM, timer); alarm(1); int stat, tmpmem, sig; for (;;) { wait4(pid, &stat, 0, &rinfo); if (WIFEXITED(stat)) { puts("exited!\n"); break; } else if (WIFSTOPPED(stat)) { sig = WSTOPSIG(stat); if (sig == SIGTRAP) { if (checkSyscall() == RET_RF) { ptrace(PTRACE_KILL, pid, NULL, NULL); final_result(RET_RF); } } else if (sig == SIGUSR1) { } else printf("Stopped due to signal: %d\n", sig); } else if (WIFSIGNALED(stat)) { //Runtime Error printf("Runtime Error. Received signal: %d\n", WTERMSIG(stat)); final_result(RET_RE); break; } tmpmem = getMemory(); if (tmpmem > maxmem) maxmem = tmpmem; if (maxmem > mlimit) final_result(RET_MLE); if (getRuntime() > tlimit) { ptrace(PTRACE_KILL, pid, NULL, NULL); final_result(RET_TLE); } ptrace(PTRACE_SYSCALL, pid, NULL, NULL); } final_result(RET_AC); return 0; }
bool f_pcntl_wifstopped(int status) { return WIFSTOPPED(status);}
int _stub (void *ep) { void *bp_ip; long ip1, op1, op2; struct user_regs_struct regs; int status, cnt; printf ("%s", "0x00pf IbI Crypter Stub\n"); // Start debugging!!! if ((_pid = fork ()) < 0) PERROR("fork:"); if (_pid == 0) return 0; // Child process just keeps running else { // Father starts debugging child if ((ptrace (PTRACE_ATTACH, _pid, NULL, NULL)) < 0) PERROR ("ptrace_attach:"); printf ("%s", "+ Waiting for process...\n"); wait (&status); bp_ip = ep; // Set breakpoint at get there... op1 = ptrace (PTRACE_PEEKTEXT, _pid, bp_ip); DPRINTF("BP: %p 1 Opcode: %lx\n", bp_ip, op1); if (ptrace (PTRACE_POKETEXT, _pid, bp_ip, (op1 & 0xFFFFFFFFFFFFFF00) | 0xcc) < 0) PERROR ("ptrace_poke:"); // Run until breakpoint is reached. if (ptrace (PTRACE_CONT, _pid, 0, 0) < 0) PERROR("ptrace_cont:"); wait (&status); ptrace (PTRACE_GETREGS, _pid, 0, ®s); DPRINTF ("Breakpoint reached: RIP: %llx\n", regs.rip); regs.rip--; ptrace (PTRACE_SETREGS, _pid, 0, ®s); // REstore opcode ptrace (PTRACE_POKETEXT, _pid, bp_ip, op1); // Start step by step debugging ip1 = (long) ep; cnt = 0; while (WIFSTOPPED (status)) { cnt ++; // Read up to 16 bytes to get the longest instruction possible // Decode and write back the decoded code to execute it op1 = ptrace (PTRACE_PEEKTEXT, _pid, ip1); op2 = ptrace (PTRACE_PEEKTEXT, _pid, ip1 + 8); DPRINTF ("%lx :: OPCODES : %lx %lx\n", ip1, op1, op2); XOR(op1); XOR(op2); DPRINTF ("%lx :: DOPCODES: %lx %lx\n", ip1, op1, op2); ptrace (PTRACE_POKETEXT, _pid, ip1, op1); ptrace (PTRACE_POKETEXT, _pid, ip1 + 8, op2); /* Make the child execute another instruction */ if (ptrace(PTRACE_SINGLESTEP, _pid, 0, 0) < 0) PERROR ("ptrace_singlestep:"); wait(&status); // Re-encode the instruction just executed so we do not have // to count how many bytes got executed XOR(op1); XOR(op2); ptrace (PTRACE_POKETEXT, _pid, ip1, op1); ptrace (PTRACE_POKETEXT, _pid, ip1 + 8, op2); // Get the new IP ptrace (PTRACE_GETREGS, _pid, 0, ®s); ip1 = regs.rip; // If code is outside .secure section we stop debugging if ((void*)ip1 < secure_ptr || (void*)ip1 > secure_ptr + secure_len) { printf ("Leaving .secure section... %d instructions executed\n", cnt); break; } } ptrace (PTRACE_CONT, _pid, 0, 0); wait (&status); } printf ("DONE\n"); exit (1); }
static void showjob(struct output *out, struct job *jp, int mode) { int procno; int st; struct procstat *ps; int col; char s[64]; #if JOBS if (mode & SHOW_PGID) { /* just output process (group) id of pipeline */ outfmt(out, "%ld\n", (long)jp->ps->pid); return; } #endif procno = jp->nprocs; if (!procno) return; if (mode & SHOW_PID) mode |= SHOW_MULTILINE; if ((procno > 1 && !(mode & SHOW_MULTILINE)) || (mode & SHOW_SIGNALLED)) { /* See if we have more than one status to report */ ps = jp->ps; st = ps->status; do { int st1 = ps->status; if (st1 != st) /* yes - need multi-line output */ mode |= SHOW_MULTILINE; if (st1 == -1 || !(mode & SHOW_SIGNALLED) || WIFEXITED(st1)) continue; if (WIFSTOPPED(st1) || ((st1 = WTERMSIG(st1) & 0x7f) && st1 != SIGINT && st1 != SIGPIPE)) mode |= SHOW_ISSIG; } while (ps++, --procno); procno = jp->nprocs; } if (mode & SHOW_SIGNALLED && !(mode & SHOW_ISSIG)) { if (jp->state == JOBDONE && !(mode & SHOW_NO_FREE)) { TRACE(("showjob: freeing job %d\n", jp - jobtab + 1)); freejob(jp); } return; } for (ps = jp->ps; --procno >= 0; ps++) { /* for each process */ if (ps == jp->ps) fmtstr(s, 16, "[%ld] %c ", (long)(jp - jobtab + 1), #if JOBS jp == jobtab + curjob ? '+' : curjob != -1 && jp == jobtab + jobtab[curjob].prev_job ? '-' : #endif ' '); else fmtstr(s, 16, " " ); col = strlen(s); if (mode & SHOW_PID) { fmtstr(s + col, 16, "%ld ", (long)ps->pid); col += strlen(s + col); } if (ps->status == -1) { scopy("Running", s + col); } else if (WIFEXITED(ps->status)) { st = WEXITSTATUS(ps->status); if (st) fmtstr(s + col, 16, "Done(%d)", st); else fmtstr(s + col, 16, "Done"); } else { #if JOBS if (WIFSTOPPED(ps->status)) st = WSTOPSIG(ps->status); else /* WIFSIGNALED(ps->status) */ #endif st = WTERMSIG(ps->status); st &= 0x7f; if (st < NSIG && sys_siglist[st]) scopyn(sys_siglist[st], s + col, 32); else fmtstr(s + col, 16, "Signal %d", st); if (WCOREDUMP(ps->status)) { col += strlen(s + col); scopyn(" (core dumped)", s + col, 64 - col); } } col += strlen(s + col); outstr(s, out); do { outc(' ', out); col++; } while (col < 30); outstr(ps->cmd, out); if (mode & SHOW_MULTILINE) { if (procno > 0) { outc(' ', out); outc('|', out); } } else { while (--procno >= 0) outfmt(out, " | %s", (++ps)->cmd ); } outc('\n', out); } flushout(out); jp->changed = 0; if (jp->state == JOBDONE && !(mode & SHOW_NO_FREE)) freejob(jp); }
STATIC int dowait(int flags, struct job *job) { int pid; int status; struct procstat *sp; struct job *jp; struct job *thisjob; int done; int stopped; TRACE(("dowait(%x) called\n", flags)); do { pid = waitproc(flags & WBLOCK, job, &status); TRACE(("wait returns pid %d, status %d\n", pid, status)); } while (pid == -1 && errno == EINTR && pendingsigs == 0); if (pid <= 0) return pid; INTOFF; thisjob = NULL; for (jp = jobtab ; jp < jobtab + njobs ; jp++) { if (jp->used) { done = 1; stopped = 1; for (sp = jp->ps ; sp < jp->ps + jp->nprocs ; sp++) { if (sp->pid == -1) continue; if (sp->pid == pid) { TRACE(("Job %d: changing status of proc %d from 0x%x to 0x%x\n", jp - jobtab + 1, pid, sp->status, status)); sp->status = status; thisjob = jp; } if (sp->status == -1) stopped = 0; else if (WIFSTOPPED(sp->status)) done = 0; } if (stopped) { /* stopped or done */ int state = done ? JOBDONE : JOBSTOPPED; if (jp->state != state) { TRACE(("Job %d: changing state from %d to %d\n", jp - jobtab + 1, jp->state, state)); jp->state = state; #if JOBS if (done) set_curjob(jp, 0); #endif } } } } if (thisjob && thisjob->state != JOBRUNNING) { int mode = 0; if (!rootshell || !iflag) mode = SHOW_SIGNALLED; if ((job == thisjob && (flags & WNOFREE) == 0) || (job != thisjob && (flags & WNOFREE) != 0)) mode = SHOW_SIGNALLED | SHOW_NO_FREE; if (mode) showjob(out2, thisjob, mode); else { TRACE(("Not printing status, rootshell=%d, job=%p\n", rootshell, job)); thisjob->changed = 1; } } INTON; return pid; }
void create_same_memory(int size, int num, int unit) { char buf[BUFSIZ], buf2[BUFSIZ]; int i, j, k; int status, fd; int *child; long ps, pages; ps = sysconf(_SC_PAGE_SIZE); pages = 1024 * 1024 / ps; child = malloc(num); if (child == NULL) tst_brkm(TBROK|TERRNO, cleanup, "malloc"); memory = malloc(num * sizeof(**memory)); if (memory == NULL) tst_brkm(TBROK|TERRNO, cleanup, "malloc"); /* Don't call cleanup in those children. Instead, do a cleanup from the parent after fetched children's status.*/ switch (child[0] = fork()) { case -1: tst_brkm(TBROK|TERRNO, cleanup, "fork"); case 0: tst_resm(TINFO, "child 0 stops."); if (raise(SIGSTOP) == -1) tst_brkm(TBROK|TERRNO, tst_exit, "kill"); tst_resm(TINFO, "child 0 continues..."); tst_resm(TINFO, "child 0 allocates %d MB filled with 'c'.", size); memory[0] = malloc(size / unit * sizeof(*memory)); if (memory[0] == NULL) tst_brkm(TBROK|TERRNO, tst_exit, "malloc"); for (j = 0; j * unit < size; j++) { memory[0][j] = mmap(NULL, unit * MB, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0); if (memory[0][j] == MAP_FAILED) tst_brkm(TBROK|TERRNO, tst_exit, "mmap"); #ifdef HAVE_MADV_MERGEABLE if (madvise(memory[0][j], unit * MB, MADV_MERGEABLE) == -1) tst_brkm(TBROK|TERRNO, tst_exit, "madvise"); #endif for (i = 0; i < unit * MB; i++) memory[0][j][i] = 'c'; } tst_resm(TINFO, "child 0 stops."); if (raise(SIGSTOP) == -1) tst_brkm(TBROK|TERRNO, tst_exit, "kill"); tst_resm(TINFO, "child 0 continues..."); verify('c', 0, 0, size / unit, 0, unit * MB); tst_resm(TINFO, "child 0 changes memory content to 'd'."); for (j = 0; j < size / unit; j++) { for (i = 0; i < unit * MB; i++) memory[0][j][i] = 'd'; } /* Unmerge. */ tst_resm(TINFO, "child 0 stops."); if (raise(SIGSTOP) == -1) tst_brkm(TBROK|TERRNO, tst_exit, "kill"); tst_resm(TINFO, "child 0 continues..."); verify('d', 0, 0, size / unit, 0, unit * MB); /* Stop. */ tst_resm(TINFO, "child 0 stops."); if (raise(SIGSTOP) == -1) tst_brkm(TBROK|TERRNO, tst_exit, "kill"); tst_resm(TINFO, "child 0 continues..."); exit(0); } switch (child[1] = fork()) { case -1: tst_brkm(TBROK|TERRNO, cleanup, "fork"); case 0: tst_resm(TINFO, "child 1 stops."); if (raise(SIGSTOP) == -1) tst_brkm(TBROK|TERRNO, tst_exit, "kill"); tst_resm(TINFO, "child 1 continues..."); tst_resm(TINFO, "child 1 allocates %d MB filled with 'a'.", size); memory[1] = malloc(size / unit * sizeof(*memory)); if (memory[1] == NULL) tst_brkm(TBROK|TERRNO, tst_exit, "malloc"); for (j = 0; j < size / unit; j++) { memory[1][j] = mmap(NULL, unit * MB, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0); if (memory[1][j] == MAP_FAILED) tst_brkm(TBROK|TERRNO, tst_exit, "mmap"); #ifdef HAVE_MADV_MERGEABLE if (madvise(memory[1][j], unit * MB, MADV_MERGEABLE) == -1) tst_brkm(TBROK|TERRNO, tst_exit, "madvise"); #endif for (i = 0; i < unit * MB; i++) memory[1][j][i] = 'a'; } tst_resm(TINFO, "child 1 stops."); if (raise(SIGSTOP) == -1) tst_brkm(TBROK|TERRNO, tst_exit, "kill"); tst_resm(TINFO, "child 1 continues..."); verify('a', 1, 0, size / unit, 0, unit * MB); tst_resm(TINFO, "child 1 changes memory content to 'b'."); for (j = 0; j < size / unit; j++) { for (i = 0; i < unit * MB; i++) memory[1][j][i] = 'b'; } tst_resm(TINFO, "child 1 stops."); if (raise(SIGSTOP) == -1) tst_brkm(TBROK|TERRNO, tst_exit, "kill"); tst_resm(TINFO, "child 1 continues..."); verify('b', 1, 0, size / unit, 0, unit * MB); tst_resm(TINFO, "child 1 changes memory content to 'd'"); for (j = 0; j < size / unit; j++) { for (i = 0; i < unit * MB; i++) memory[1][j][i] = 'd'; } if (raise(SIGSTOP) == -1) tst_brkm(TBROK|TERRNO, tst_exit, "kill"); tst_resm(TINFO, "child 1 continues..."); verify('d', 1, 0, size / unit, 0, unit * MB); tst_resm(TINFO, "child 1 changes one page to 'e'."); memory[1][size / unit - 1][unit * MB - 1] = 'e'; /* Unmerge. */ tst_resm(TINFO, "child 1 stops."); if (raise(SIGSTOP) == -1) tst_brkm(TBROK|TERRNO, tst_exit, "kill"); tst_resm(TINFO, "child 1 continues..."); verify('e', 1, size / unit - 1, size / unit, unit * MB - 1, unit * MB); verify('d', 1, 0, size / unit - 1, 0, unit * MB - 1); /* Stop. */ tst_resm(TINFO, "child 1 stops."); if (raise(SIGSTOP) == -1) tst_brkm(TBROK|TERRNO, tst_exit, "kill"); tst_resm(TINFO, "child 1 continues..."); exit(0); } for (k = 2; k < num; k++) { switch (child[k] = fork()) { case -1: tst_brkm(TBROK|TERRNO, cleanup, "fork"); case 0: tst_resm(TINFO, "child %d stops.", k); if (raise(SIGSTOP) == -1) tst_brkm(TBROK|TERRNO, tst_exit, "kill"); tst_resm(TINFO, "child %d continues...", k); tst_resm(TINFO, "child %d allocates %d " "MB filled with 'a'.", k, size); memory[k] = malloc(size / unit * sizeof(*memory)); if (memory[k] == NULL) tst_brkm(TBROK|TERRNO, tst_exit, "malloc"); for (j = 0; j < size / unit; j++) { memory[k][j] = mmap(NULL, unit * MB, PROT_READ|PROT_WRITE, MAP_ANONYMOUS |MAP_PRIVATE, -1, 0); if (memory[k][j] == MAP_FAILED) tst_brkm(TBROK|TERRNO, cleanup, "mmap"); #ifdef HAVE_MADV_MERGEABLE if (madvise(memory[k][j], unit * MB, MADV_MERGEABLE) == -1) tst_brkm(TBROK|TERRNO, cleanup, "madvise"); #endif for (i = 0; i < unit * MB; i++) memory[k][j][i] = 'a'; } tst_resm(TINFO, "child %d stops.", k); if (raise(SIGSTOP) == -1) tst_brkm(TBROK|TERRNO, tst_exit, "kill"); tst_resm(TINFO, "child %d continues...", k); tst_resm(TINFO, "child %d changes memory content to " "'d'", k); for (j = 0; j < size / unit; j++) { for (i = 0; i < unit * MB; i++) memory[k][j][i] = 'd'; } /* Unmerge. */ tst_resm(TINFO, "child %d stops.", k); if (raise(SIGSTOP) == -1) tst_brkm(TBROK|TERRNO, tst_exit, "kill"); tst_resm(TINFO, "child %d continues...", k); /* Stop. */ tst_resm(TINFO, "child %d stops.", k); if (raise(SIGSTOP) == -1) tst_brkm(TBROK|TERRNO, tst_exit, "kill"); tst_resm(TINFO, "child %d continues...", k); exit(0); } } tst_resm(TINFO, "KSM merging..."); snprintf(buf, BUFSIZ, "%s%s", PATH_KSM, "run"); fd = open(buf, O_WRONLY); if (fd == -1) tst_brkm(TBROK|TERRNO, cleanup, "open"); if (write(fd, "1", 1) != 1) tst_brkm(TBROK|TERRNO, cleanup, "write"); close(fd); snprintf(buf, BUFSIZ, "%s%s", PATH_KSM, "pages_to_scan"); snprintf(buf2, BUFSIZ, "%ld", size * pages * num); fd = open(buf, O_WRONLY); if (fd == -1) tst_brkm(TBROK|TERRNO, cleanup, "open"); if (write(fd, buf2, strlen(buf2)) != strlen(buf2)) tst_brkm(TBROK|TERRNO, cleanup, "write"); close(fd); snprintf(buf, BUFSIZ, "%s%s", PATH_KSM, "sleep_millisecs"); fd = open(buf, O_WRONLY); if (fd == -1) tst_brkm(TBROK|TERRNO, cleanup, "open"); if (write(fd, "0", 1) != 1) tst_brkm(TBROK|TERRNO, cleanup, "write"); close(fd); tst_resm(TINFO, "wait for all children to stop."); for (k = 0; k < num; k++) { if (waitpid(child[k], &status, WUNTRACED) == -1) tst_brkm(TBROK|TERRNO, cleanup, "waitpid"); if (!WIFSTOPPED(status)) tst_brkm(TBROK, cleanup, "child %d was not stopped.", k); } tst_resm(TINFO, "resume all children."); for (k = 0; k < num; k++) { if (kill(child[k], SIGCONT) == -1) tst_brkm(TBROK|TERRNO, cleanup, "kill child[%d]", k); } group_check(1, 2, size * num * pages - 2, 0, 0, 0, size * pages * num); tst_resm(TINFO, "wait for child 1 to stop."); if (waitpid(child[1], &status, WUNTRACED) == -1) tst_brkm(TBROK|TERRNO, cleanup, "waitpid"); if (!WIFSTOPPED(status)) tst_brkm(TBROK, cleanup, "child 1 was not stopped."); /* Child 1 changes all pages to 'b'. */ tst_resm(TINFO, "resume child 1."); if (kill(child[1], SIGCONT) == -1) tst_brkm(TBROK|TERRNO, cleanup, "kill"); group_check(1, 3, size * num * pages - 3, 0, 0, 0, size * pages * num); tst_resm(TINFO, "wait for child 1 to stop."); if (waitpid(child[1], &status, WUNTRACED) == -1) tst_brkm(TBROK|TERRNO, cleanup, "waitpid"); if (!WIFSTOPPED(status)) tst_brkm(TBROK, cleanup, "child 1 was not stopped."); /* All children change pages to 'd'. */ tst_resm(TINFO, "resume all children."); for (k = 0; k < num; k++) { if (kill(child[k], SIGCONT) == -1) tst_brkm(TBROK|TERRNO, cleanup, "kill child[%d]", k); } group_check(1, 1, size * num * pages - 1, 0, 0, 0, size * pages * num); tst_resm(TINFO, "wait for all children to stop."); for (k = 0; k < num; k++) { if (waitpid(child[k], &status, WUNTRACED) == -1) tst_brkm(TBROK|TERRNO, cleanup, "waitpid"); if (!WIFSTOPPED(status)) tst_brkm(TBROK, cleanup, "child %d was not stopped.", k); } /* Child 1 changes pages to 'e'. */ tst_resm(TINFO, "resume child 1."); if (kill(child[1], SIGCONT) == -1) tst_brkm(TBROK|TERRNO, cleanup, "kill"); group_check(1, 1, size * num * pages - 2, 0, 1, 0, size * pages * num); tst_resm(TINFO, "wait for child 1 to stop."); if (waitpid(child[1], &status, WUNTRACED) == -1) tst_brkm(TBROK|TERRNO, cleanup, "waitpid"); if (!WIFSTOPPED(status)) tst_brkm(TBROK, cleanup, "child 1 was not stopped."); tst_resm(TINFO, "resume all children."); for (k = 0; k < num; k++) { if (kill(child[k], SIGCONT) == -1) tst_brkm(TBROK|TERRNO, cleanup, "kill child[%d]", k); } tst_resm(TINFO, "KSM unmerging..."); snprintf(buf, BUFSIZ, "%s%s", PATH_KSM, "run"); fd = open(buf, O_WRONLY); if (fd == -1) tst_brkm(TBROK|TERRNO, cleanup, "open"); if (write(fd, "2", 1) != 1) tst_brkm(TBROK|TERRNO, cleanup, "write"); group_check(2, 0, 0, 0, 0, 0, size * pages * num); tst_resm(TINFO, "wait for all children to stop."); for (k = 0; k < num; k++) { if (waitpid(child[k], &status, WUNTRACED) == -1) tst_brkm(TBROK|TERRNO, cleanup, "waitpid"); if (!WIFSTOPPED(status)) tst_brkm(TBROK, cleanup, "child %d was not stopped.", k); } tst_resm(TINFO, "resume all children."); for (k = 0; k < num; k++) { if (kill(child[k], SIGCONT) == -1) tst_brkm(TBROK|TERRNO, cleanup, "kill child[%d]", k); } tst_resm(TINFO, "stop KSM."); if (lseek(fd, 0, SEEK_SET) == -1) tst_brkm(TBROK|TERRNO, cleanup, "lseek"); if (write(fd, "0", 1) != 1) tst_brkm(TBROK|TERRNO, cleanup, "write"); close(fd); group_check(0, 0, 0, 0, 0, 0, size * pages * num); while (waitpid(-1, &status, WUNTRACED | WCONTINUED) > 0) if (WEXITSTATUS(status) != 0) tst_resm(TFAIL, "child exit status is %d", WEXITSTATUS(status)); }
int main(int argc, char **argv) { sigset_t oldmask, newmask; pid_t pid; int status; int exitcode; char *valid_users; char *ptr; char *path; char cwd[MAXPATHLEN+3]; int opt; struct rlimit lim; progname = argv[0]; /* Clear environment to prevent all kinds of security holes, save PATH */ path = getenv("PATH"); environ[0] = NULL; /* FIXME: Clean path before setting it again? */ if ( path!=NULL ) setenv("PATH",path,1); /* Parse command-line options */ use_root = use_time = use_user = use_output = no_coredump = 0; memsize = filesize = nproc = RLIM_INFINITY; be_verbose = be_quiet = 0; show_help = show_version = 0; opterr = 0; while ( (opt = getopt_long(argc,argv,"+r:t:u:m:f:p:co:vq",long_opts,(int *) 0))!=-1 ) { switch ( opt ) { case 0: /* long-only option */ break; case 'r': /* rootdir option */ use_root = 1; rootdir = (char *) malloc(strlen(optarg)+2); strcpy(rootdir,optarg); break; case 't': /* time option */ use_time = 1; runtime = strtol(optarg,&ptr,10); if ( *ptr!=0 || runtime<=0 ) { error(0,"invalid time specified: `%s'",optarg); } break; case 'u': /* user option */ use_user = 1; runuid = strtol(optarg,&ptr,10); if ( *ptr!=0 ) runuid = userid(optarg); if ( runuid<0 ) error(0,"invalid username or ID specified: `%s'",optarg); break; case 'm': /* memsize option */ memsize = (rlim_t) strtol(optarg,&ptr,10); if ( *ptr!=0 || memsize<=0 ) { error(0,"invalid memory limit specified: `%s'",optarg); } /* Convert limit from kB to bytes and check for overflow */ if ( memsize!=(memsize*1024)/1024 ) { memsize = RLIM_INFINITY; } else { memsize *= 1024; } break; case 'f': /* filesize option */ filesize = (rlim_t) strtol(optarg,&ptr,10); if ( *ptr!=0 || filesize<=0 ) { error(0,"invalid filesize limit specified: `%s'",optarg); } /* Convert limit from kB to bytes and check for overflow */ if ( filesize!=(filesize*1024)/1024 ) { filesize = RLIM_INFINITY; } else { filesize *= 1024; } break; case 'p': /* nproc option */ nproc = (rlim_t) strtol(optarg,&ptr,10); if ( *ptr!=0 || nproc<=0 ) { error(0,"invalid process limit specified: `%s'",optarg); } break; case 'c': /* no-core option */ no_coredump = 1; break; case 'o': /* output option */ use_output = 1; outputfilename = (char *) malloc(strlen(optarg)+2); strcpy(outputfilename,optarg); break; case 'v': /* verbose option */ be_verbose = 1; break; case 'q': /* quiet option */ be_quiet = 1; break; case ':': /* getopt error */ case '?': error(0,"unknown option or missing argument `%c'",optopt); break; default: error(0,"getopt returned character code `%c' ??",(char)opt); } } if ( show_help ) usage(); if ( show_version ) version(); if ( argc<=optind ) error(0,"no command specified"); /* Command to be executed */ cmdname = argv[optind]; cmdargs = argv+optind; /* Check that new uid is in list of valid uid's. This must be done before chroot for /etc/passwd lookup. */ if ( use_user ) { valid_users = strdup(VALID_USERS); for(ptr=strtok(valid_users,","); ptr!=NULL; ptr=strtok(NULL,",")) { if ( runuid==userid(ptr) ) break; } if ( ptr==NULL || runuid<=0 ) error(0,"illegal user specified: %d",runuid); } /* Set resource limits: must be root to raise hard limits. Note that limits can thus be raised from the systems defaults! */ /* First define shorthand macro function */ #define setlim(type) \ if ( setrlimit(RLIMIT_ ## type, &lim)!=0 ) { \ if ( errno==EPERM ) { \ warning("no permission to set resource RLIMIT_" #type); \ } else { \ error(errno,"setting resource RLIMIT_" #type); \ } \ } if ( memsize!=RLIM_INFINITY ) { verbose("setting memory limits to %d bytes",(int)memsize); } lim.rlim_cur = lim.rlim_max = memsize; setlim(AS); setlim(DATA); setlim(STACK); setlim(MEMLOCK); if ( filesize!=RLIM_INFINITY ) { verbose("setting filesize limit to %d bytes",(int)filesize); } lim.rlim_cur = lim.rlim_max = filesize; setlim(FSIZE); if ( nproc!=RLIM_INFINITY ) { verbose("setting process limit to %d",(int)nproc); } lim.rlim_cur = lim.rlim_max = nproc; setlim(NPROC); #undef setlim if ( no_coredump ) { verbose("disabling core dumps"); lim.rlim_cur = lim.rlim_max = 0; if ( setrlimit(RLIMIT_CORE,&lim)!=0 ) error(errno,"disabling core dumps"); } /* Set root-directory and change directory to there. */ if ( use_root ) { /* Small security issue: when running setuid-root, people can find out which directories exist from error message. */ if ( chdir(rootdir) ) error(errno,"cannot chdir to `%s'",rootdir); /* Get absolute pathname of rootdir, by reading it. */ if ( getcwd(cwd,MAXPATHLEN)==NULL ) error(errno,"cannot get directory"); if ( cwd[strlen(cwd)-1]!='/' ) strcat(cwd,"/"); /* Canonicalize CHROOT_PREFIX: the use of NULL below is a GNU extension, recommended for security */ if ( (path = realpath(CHROOT_PREFIX,NULL))==NULL ) { error(errno,"cannot canonicalize path '%s'",CHROOT_PREFIX); } /* Check that we are within prescribed path. */ if ( strncmp(cwd,path,strlen(path))!=0 ) { error(0,"invalid root: must be within `%s'",path); } free(path); if ( chroot(".") ) error(errno,"cannot change root to `%s'",cwd); verbose("using root-directory `%s'",cwd); } /* Set user-id (must be root for this). */ if ( use_user ) { if ( setuid(runuid) ) error(errno,"cannot set user ID to `%d'",runuid); verbose("using user ID `%d'",runuid); } else { /* Reset effective uid to real uid, to increase security when program is run setuid */ if ( setuid(getuid()) ) error(errno,"cannot set real user ID"); verbose("using real uid `%d' as effective uid",getuid()); } if ( geteuid()==0 || getuid()==0 ) error(0,"root privileges not dropped"); /* Open output file for writing running time to */ if ( use_output ) { outputfile = fopen(outputfilename,"w"); if ( outputfile==NULL ) error(errno,"cannot open `%s'",outputfilename); verbose("using file `%s' to write runtime to",outputfilename); } switch ( child_pid = fork() ) { case -1: /* error */ error(errno,"cannot fork"); case 0: /* run controlled command */ /* Run the command in a separate process group so that the command and all its children can be killed off with one signal. */ setsid(); execvp(cmdname,cmdargs); error(errno,"cannot start `%s'",cmdname); default: /* become watchdog */ if ( gettimeofday(&starttime,NULL) ) error(errno,"getting time"); /* unmask all signals */ memset(&newmask, 0, sizeof(newmask)); if ( sigprocmask(SIG_SETMASK, &newmask, &oldmask)!=0 ) { error(errno,"unmasking signals"); } signal(SIGTERM,terminate); if ( use_time ) { signal(SIGALRM,terminate); alarm(runtime); verbose("using timelimit of %d seconds",runtime); } /* Wait for the child command to finish */ while ( (pid = wait(&status))!=-1 && pid!=child_pid ); if ( pid!=child_pid ) error(errno,"waiting on child"); outputtime(); /* Test whether command has finished abnormally */ if ( ! WIFEXITED(status) ) { if ( WIFSIGNALED(status) ) { warning("command terminated with signal %d",WTERMSIG(status)); return 128+WTERMSIG(status); } if ( WIFSTOPPED(status) ) { warning("command stopped with signal %d",WSTOPSIG(status)); return 128+WSTOPSIG(status); } error(0,"command exit status unknown: %d",status); } /* Return the exitstatus of the command */ exitcode = WEXITSTATUS(status); if ( exitcode!=0 ) verbose("command exited with exitcode %d",exitcode); return exitcode; } /* This should never be reached */ error(0,"unexpected end of program"); }
int main(int argc, char *argv[]) { int exit_status = 0, ret, flags = 0, i; int exec_argc = 0, user_argc = 0; char **exec_argv = NULL, **user_argv = NULL; char *exec_command, *base_argv0 = NULL; bool disable_flags = true; bool real_flag = false; if (OPAL_SUCCESS != (ret = opal_init_util(&argc, &argv))) { return ret; } /**************************************************** * * Setup compiler information * ****************************************************/ base_argv0 = opal_basename(argv[0]); #if defined(EXEEXT) if( 0 != strlen(EXEEXT) ) { char extension[] = EXEEXT; char* temp = strstr( base_argv0, extension ); char* old_match = temp; while( NULL != temp ) { old_match = temp; temp = strstr( temp + 1, extension ); } /* Only if there was a match of .exe, erase the last occurence of .exe */ if ( NULL != old_match ) { *old_match = '\0'; } } #endif /* defined(EXEEXT) */ if (OPAL_SUCCESS != (ret = data_init(base_argv0))) { fprintf(stderr, "Error parsing data file %s: %s\n", base_argv0, opal_strerror(ret)); return ret; } for (i = 1 ; i < argc && user_data_idx < 0 ; ++i) { user_data_idx = find_options_index(argv[i]); } /* if we didn't find a match, look for the NULL (base case) options */ if (user_data_idx < 0) { user_data_idx = default_data_idx; } /* if we still didn't find a match, abort */ if (user_data_idx < 0) { char *flat = opal_argv_join(argv, ' '); opal_show_help("help-opal-wrapper.txt", "no-options-support", true, base_argv0, flat, NULL); free(flat); exit(1); } /* compiler */ load_env_data(options_data[user_data_idx].project_short, options_data[user_data_idx].compiler_env, &options_data[user_data_idx].compiler); /* preprocessor flags */ load_env_data_argv(options_data[user_data_idx].project_short, "CPPFLAGS", &options_data[user_data_idx].preproc_flags); /* compiler flags */ load_env_data_argv(options_data[user_data_idx].project_short, options_data[user_data_idx].compiler_flags_env, &options_data[user_data_idx].comp_flags); /* linker flags */ load_env_data_argv(options_data[user_data_idx].project_short, "LDFLAGS", &options_data[user_data_idx].link_flags); /* libs */ load_env_data_argv(options_data[user_data_idx].project_short, "LIBS", &options_data[user_data_idx].libs); /**************************************************** * * Sanity Checks * ****************************************************/ if (NULL != options_data[user_data_idx].req_file) { /* make sure the language is supported */ if (0 == strcmp(options_data[user_data_idx].req_file, "not supported")) { opal_show_help("help-opal-wrapper.txt", "no-language-support", true, options_data[user_data_idx].language, base_argv0, NULL); exit_status = 1; goto cleanup; } if (options_data[user_data_idx].req_file[0] != '\0') { char *filename; struct stat buf; filename = opal_os_path( false, options_data[user_data_idx].path_libdir, options_data[user_data_idx].req_file, NULL ); if (0 != stat(filename, &buf)) { opal_show_help("help-opal-wrapper.txt", "file-not-found", true, base_argv0, options_data[user_data_idx].req_file, options_data[user_data_idx].language, NULL); } } } /**************************************************** * * Parse user flags * ****************************************************/ flags = COMP_WANT_COMMAND|COMP_WANT_PREPROC| COMP_WANT_COMPILE|COMP_WANT_LINK; user_argv = opal_argv_copy(argv + 1); user_argc = opal_argv_count(user_argv); for (i = 0 ; i < user_argc ; ++i) { if (0 == strncmp(user_argv[i], "-showme", strlen("-showme")) || 0 == strncmp(user_argv[i], "--showme", strlen("--showme")) || 0 == strncmp(user_argv[i], "-show", strlen("-show")) || 0 == strncmp(user_argv[i], "--show", strlen("--show"))) { bool done_now = false; /* check for specific things we want to see. First three still invoke all the building routines. Last set want to parse out certain flags, so we don't go through the normal build routine - skip to cleanup. */ if (0 == strncmp(user_argv[i], "-showme:command", strlen("-showme:command")) || 0 == strncmp(user_argv[i], "--showme:command", strlen("--showme:command"))) { flags = COMP_WANT_COMMAND; /* we know what we want, so don't process any more args */ done_now = true; } else if (0 == strncmp(user_argv[i], "-showme:compile", strlen("-showme:compile")) || 0 == strncmp(user_argv[i], "--showme:compile", strlen("--showme:compile"))) { flags = COMP_WANT_PREPROC|COMP_WANT_COMPILE; /* we know what we want, so don't process any more args */ done_now = true; } else if (0 == strncmp(user_argv[i], "-showme:link", strlen("-showme:link")) || 0 == strncmp(user_argv[i], "--showme:link", strlen("--showme:link"))) { flags = COMP_WANT_COMPILE|COMP_WANT_LINK; /* we know what we want, so don't process any more args */ done_now = true; } else if (0 == strncmp(user_argv[i], "-showme:incdirs", strlen("-showme:incdirs")) || 0 == strncmp(user_argv[i], "--showme:incdirs", strlen("--showme:incdirs"))) { print_flags(options_data[user_data_idx].preproc_flags, OPAL_INCLUDE_FLAG); goto cleanup; } else if (0 == strncmp(user_argv[i], "-showme:libdirs", strlen("-showme:libdirs")) || 0 == strncmp(user_argv[i], "--showme:libdirs", strlen("--showme:libdirs"))) { print_flags(options_data[user_data_idx].link_flags, OPAL_LIBDIR_FLAG); goto cleanup; } else if (0 == strncmp(user_argv[i], "-showme:libs", strlen("-showme:libs")) || 0 == strncmp(user_argv[i], "--showme:libs", strlen("--showme:libs"))) { print_flags(options_data[user_data_idx].libs, "-l"); goto cleanup; } else if (0 == strncmp(user_argv[i], "-showme:version", strlen("-showme:version")) || 0 == strncmp(user_argv[i], "--showme:version", strlen("--showme:version"))) { char * str; str = opal_show_help_string("help-opal-wrapper.txt", "version", false, argv[0], options_data[user_data_idx].project, options_data[user_data_idx].version, options_data[user_data_idx].language, NULL); if (NULL != str) { printf("%s", str); free(str); } goto cleanup; } else if (0 == strncmp(user_argv[i], "-showme:help", strlen("-showme:help")) || 0 == strncmp(user_argv[i], "--showme:help", strlen("--showme:help"))) { char *str; str = opal_show_help_string("help-opal-wrapper.txt", "usage", false, argv[0], options_data[user_data_idx].project, NULL); if (NULL != str) { printf("%s", str); free(str); } exit_status = 0; goto cleanup; } else if (0 == strncmp(user_argv[i], "-showme:", strlen("-showme:")) || 0 == strncmp(user_argv[i], "--showme:", strlen("--showme:"))) { fprintf(stderr, "%s: unrecognized option: %s\n", argv[0], user_argv[i]); fprintf(stderr, "Type '%s --showme:help' for usage.\n", argv[0]); exit_status = 1; goto cleanup; } flags |= (COMP_DRY_RUN|COMP_SHOW_ERROR); /* remove element from user_argv */ opal_argv_delete(&user_argc, &user_argv, i, 1); --i; if (done_now) { disable_flags = false; break; } } else if (0 == strcmp(user_argv[i], "-c")) { flags &= ~COMP_WANT_LINK; real_flag = true; } else if (0 == strcmp(user_argv[i], "-E") || 0 == strcmp(user_argv[i], "-M")) { flags &= ~(COMP_WANT_COMPILE | COMP_WANT_LINK); real_flag = true; } else if (0 == strcmp(user_argv[i], "-S")) { flags &= ~COMP_WANT_LINK; real_flag = true; } else if (0 == strcmp(user_argv[i], "-lpmpi")) { flags |= COMP_WANT_PMPI; /* remove element from user_argv */ opal_argv_delete(&user_argc, &user_argv, i, 1); --i; } else if (0 == strcmp(user_argv[i], "-static") || 0 == strcmp(user_argv[i], "--static") || 0 == strcmp(user_argv[i], "-Bstatic") || 0 == strcmp(user_argv[i], "-Wl,-static") || 0 == strcmp(user_argv[i], "-Wl,--static") || 0 == strcmp(user_argv[i], "-Wl,-Bstatic")) { flags |= COMP_WANT_STATIC; } else if (0 == strcmp(user_argv[i], "-dynamic") || 0 == strcmp(user_argv[i], "--dynamic") || 0 == strcmp(user_argv[i], "-Bdynamic") || 0 == strcmp(user_argv[i], "-Wl,-dynamic") || 0 == strcmp(user_argv[i], "-Wl,--dynamic") || 0 == strcmp(user_argv[i], "-Wl,-Bdynamic")) { flags &= ~COMP_WANT_STATIC; } else if (0 == strcmp(user_argv[i], "--openmpi:linkall")) { /* This is an intentionally undocummented wrapper compiler switch. It should only be used by Open MPI developers -- not end users. It will cause mpicc to use the static library list, even if we're compiling dynamically (i.e., it'll specifically -lopen-rte and -lopen-pal (and all their dependent libs)). We provide this flag for test MPI applications that also invoke ORTE and/or OPAL function calls. On some systems (e.g., OS X), if the top-level application calls ORTE/OPAL functions and you don't -l ORTE and OPAL, then the functions won't be resolved at link time (i.e., the implicit library dependencies of libmpi won't be pulled in at link time), and therefore the link will fail. This flag will cause the wrapper to explicitly list the ORTE and OPAL libs on the underlying compiler command line, so the application will therefore link properly. */ flags |= COMP_WANT_LINKALL; /* remove element from user_argv */ opal_argv_delete(&user_argc, &user_argv, i, 1); } else if ('-' != user_argv[i][0]) { disable_flags = false; flags |= COMP_SHOW_ERROR; real_flag = true; } else { /* if the option flag is one that we use to determine which set of compiler data to use, don't count it as a real option */ if (find_options_index(user_argv[i]) < 0) { real_flag = true; } } } /* clear out the want_flags if we got no arguments not starting with a - (dash) and -showme wasn't given OR -showme was given and we had at least one more non-showme argument that started with a - (dash) and no other non-dash arguments. Some examples: opal_wrapper : clear our flags opal_wrapper -v : clear our flags opal_wrapper -E a.c : don't clear our flags opal_wrapper a.c : don't clear our flags opal_wrapper -showme : don't clear our flags opal_wrapper -showme -v : clear our flags opal_wrapper -showme -E a.c : don't clear our flags opal_wrapper -showme a.c : don't clear our flags */ if (disable_flags && !((flags & COMP_DRY_RUN) && !real_flag)) { flags &= ~(COMP_WANT_PREPROC|COMP_WANT_COMPILE|COMP_WANT_LINK); } /**************************************************** * * Assemble the command line * ****************************************************/ /* compiler (may be multiple arguments, so split) */ if (flags & COMP_WANT_COMMAND) { exec_argv = opal_argv_split(options_data[user_data_idx].compiler, ' '); exec_argc = opal_argv_count(exec_argv); } else { exec_argv = (char **) malloc(sizeof(char*)); exec_argv[0] = NULL; exec_argc = 0; } /* This error would normally not happen unless the user edits the wrapper data files manually */ if (NULL == exec_argv) { opal_show_help("help-opal-wrapper.txt", "no-compiler-specified", true); return 1; } if (flags & COMP_WANT_COMPILE) { opal_argv_insert(&exec_argv, exec_argc, options_data[user_data_idx].comp_flags_prefix); exec_argc = opal_argv_count(exec_argv); } /* Per https://svn.open-mpi.org/trac/ompi/ticket/2201, add all the user arguments before anything else. */ opal_argv_insert(&exec_argv, exec_argc, user_argv); exec_argc = opal_argv_count(exec_argv); /* preproc flags */ if (flags & COMP_WANT_PREPROC) { opal_argv_insert(&exec_argv, exec_argc, options_data[user_data_idx].preproc_flags); exec_argc = opal_argv_count(exec_argv); } /* compiler flags */ if (flags & COMP_WANT_COMPILE) { opal_argv_insert(&exec_argv, exec_argc, options_data[user_data_idx].comp_flags); exec_argc = opal_argv_count(exec_argv); } /* link flags and libs */ if (flags & COMP_WANT_LINK) { bool have_static_lib; bool have_dyn_lib; bool use_static_libs; char *filename1, *filename2; struct stat buf; opal_argv_insert(&exec_argv, exec_argc, options_data[user_data_idx].link_flags); exec_argc = opal_argv_count(exec_argv); /* Are we linking statically? If so, decide what libraries to list. It depends on two factors: 1. Was --static (etc.) specified? 2. Does OMPI have static, dynamic, or both libraries installed? Here's a matrix showing what we'll do in all 6 cases: What's installed --static no --static ---------------- ---------- ----------- ompi .so libs -lmpi -lmpi ompi .a libs all all ompi both libs all -lmpi */ filename1 = opal_os_path( false, options_data[user_data_idx].path_libdir, options_data[user_data_idx].static_lib_file, NULL ); if (0 == stat(filename1, &buf)) { have_static_lib = true; } else { have_static_lib = false; } filename2 = opal_os_path( false, options_data[user_data_idx].path_libdir, options_data[user_data_idx].dyn_lib_file, NULL ); if (0 == stat(filename2, &buf)) { have_dyn_lib = true; } else { have_dyn_lib = false; } /* Determine which set of libs to use: dynamic or static. Be pedantic to make the code easy to read. */ if (flags & COMP_WANT_LINKALL) { /* If --openmpi:linkall was specified, list all the libs (i.e., the static libs) if they're available, either in static or dynamic form. */ if (have_static_lib || have_dyn_lib) { use_static_libs = true; } else { fprintf(stderr, "The linkall option has failed as we were unable to find either static or dynamic libs\n" "Files looked for:\n Static: %s\n Dynamic: %s\n", filename1, filename2); free(filename1); free(filename2); exit(1); } } else if (flags & COMP_WANT_STATIC) { /* If --static (or something like it) was specified, if we have the static libs, then use them. Otherwise, use the dynamic libs. */ if (have_static_lib) { use_static_libs = true; } else { use_static_libs = false; } } else { /* If --static (or something like it) was NOT specified (or if --dyanic, or something like it, was specified), if we have the dynamic libs, then use them. Otherwise, use the static libs. */ if (have_dyn_lib) { use_static_libs = false; } else { use_static_libs = true; } } free(filename1); free(filename2); if (use_static_libs) { opal_argv_insert(&exec_argv, exec_argc, options_data[user_data_idx].libs_static); } else { opal_argv_insert(&exec_argv, exec_argc, options_data[user_data_idx].libs); } exec_argc = opal_argv_count(exec_argv); } /**************************************************** * * Execute the command * ****************************************************/ if (flags & COMP_DRY_RUN) { exec_command = opal_argv_join(exec_argv, ' '); printf("%s\n", exec_command); } else { char *tmp; #if 0 exec_command = opal_argv_join(exec_argv, ' '); printf("command: %s\n", exec_command); #endif tmp = opal_path_findv(exec_argv[0], 0, environ, NULL); if (NULL == tmp) { opal_show_help("help-opal-wrapper.txt", "no-compiler-found", true, exec_argv[0], NULL); errno = 0; exit_status = 1; } else { int status; free(exec_argv[0]); exec_argv[0] = tmp; ret = opal_few(exec_argv, &status); exit_status = WIFEXITED(status) ? WEXITSTATUS(status) : (WIFSIGNALED(status) ? WTERMSIG(status) : (WIFSTOPPED(status) ? WSTOPSIG(status) : 255)); if( (OPAL_SUCCESS != ret) || ((0 != exit_status) && (flags & COMP_SHOW_ERROR)) ) { char* exec_command = opal_argv_join(exec_argv, ' '); if( OPAL_SUCCESS != ret ) { opal_show_help("help-opal-wrapper.txt", "spawn-failed", true, exec_argv[0], strerror(status), exec_command, NULL); } else { #if 0 opal_show_help("help-opal-wrapper.txt", "compiler-failed", true, exec_argv[0], exit_status, exec_command, NULL); #endif } free(exec_command); } } } /**************************************************** * * Cleanup * ****************************************************/ cleanup: opal_argv_free(exec_argv); opal_argv_free(user_argv); if (NULL != base_argv0) free(base_argv0); if (OPAL_SUCCESS != (ret = data_finalize())) { return ret; } if (OPAL_SUCCESS != (ret = opal_finalize_util())) { return ret; } return exit_status; }
int tracer(int (*init_proc)(void *), void *sp) { void *task = NULL; unsigned long eip = 0; int status, pid = 0, sig = 0, cont_type, tracing = 0, op = 0; int last_index, proc_id = 0, n, err, old_tracing = 0, strace = 0; capture_signal_stack(); signal(SIGPIPE, SIG_IGN); setup_tracer_winch(); tracing_pid = os_getpid(); printf("tracing thread pid = %d\n", tracing_pid); pid = clone(signal_tramp, sp, CLONE_FILES | SIGCHLD, init_proc); CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); if(n < 0){ printf("waitpid on idle thread failed, errno = %d\n", errno); exit(1); } if((ptrace(PTRACE_CONT, pid, 0, 0) < 0)){ printf("Failed to continue idle thread, errno = %d\n", errno); exit(1); } signal(SIGSEGV, (sighandler_t) tracer_segv); signal(SIGUSR1, signal_usr1); if(debug_trace){ printf("Tracing thread pausing to be attached\n"); stop(); } if(debug){ if(gdb_pid != -1) debugger_pid = attach_debugger(pid, gdb_pid, 1); else debugger_pid = init_ptrace_proxy(pid, 1, debug_stop); if(debug_parent){ debugger_parent = os_process_parent(debugger_pid); init_parent_proxy(debugger_parent); err = attach(debugger_parent); if(err){ printf("Failed to attach debugger parent %d, " "errno = %d\n", debugger_parent, -err); debugger_parent = -1; } else { if(ptrace(PTRACE_SYSCALL, debugger_parent, 0, 0) < 0){ printf("Failed to continue debugger " "parent, errno = %d\n", errno); debugger_parent = -1; } } } } set_cmdline("(tracing thread)"); while(1){ CATCH_EINTR(pid = waitpid(-1, &status, WUNTRACED)); if(pid <= 0){ if(errno != ECHILD){ printf("wait failed - errno = %d\n", errno); } continue; } if(pid == debugger_pid){ int cont = 0; if(WIFEXITED(status) || WIFSIGNALED(status)) debugger_pid = -1; /* XXX Figure out how to deal with gdb and SMP */ else cont = debugger_signal(status, cpu_tasks[0].pid); if(cont == PTRACE_SYSCALL) strace = 1; continue; } else if(pid == debugger_parent){ debugger_parent_signal(status, pid); continue; } nsignals++; if(WIFEXITED(status)) ; #ifdef notdef { printf("Child %d exited with status %d\n", pid, WEXITSTATUS(status)); } #endif else if(WIFSIGNALED(status)){ sig = WTERMSIG(status); if(sig != 9){ printf("Child %d exited with signal %d\n", pid, sig); } } else if(WIFSTOPPED(status)){ proc_id = pid_to_processor_id(pid); sig = WSTOPSIG(status); if(signal_index[proc_id] == 1024){ signal_index[proc_id] = 0; last_index = 1023; } else last_index = signal_index[proc_id] - 1; if(((sig == SIGPROF) || (sig == SIGVTALRM) || (sig == SIGALRM)) && (signal_record[proc_id][last_index].signal == sig)&& (signal_record[proc_id][last_index].pid == pid)) signal_index[proc_id] = last_index; signal_record[proc_id][signal_index[proc_id]].pid = pid; gettimeofday(&signal_record[proc_id][signal_index[proc_id]].time, NULL); eip = ptrace(PTRACE_PEEKUSER, pid, PT_IP_OFFSET, 0); signal_record[proc_id][signal_index[proc_id]].addr = eip; signal_record[proc_id][signal_index[proc_id]++].signal = sig; if(proc_id == -1){ sleeping_process_signal(pid, sig); continue; } task = cpu_tasks[proc_id].task; tracing = is_tracing(task); old_tracing = tracing; switch(sig){ case SIGUSR1: sig = 0; op = do_proc_op(task, proc_id); switch(op){ case OP_TRACE_ON: arch_leave_kernel(task, pid); tracing = 1; break; case OP_REBOOT: case OP_HALT: unmap_physmem(); kmalloc_ok = 0; ptrace(PTRACE_KILL, pid, 0, 0); return(op == OP_REBOOT); case OP_NONE: printf("Detaching pid %d\n", pid); detach(pid, SIGSTOP); continue; default: break; } /* OP_EXEC switches host processes on us, * we want to continue the new one. */ pid = cpu_tasks[proc_id].pid; break; case SIGTRAP: if(!tracing && (debugger_pid != -1)){ child_signal(pid, status); continue; } tracing = 0; if(do_syscall(task, pid)) sig = SIGUSR2; else clear_singlestep(task); break; case SIGPROF: if(tracing) sig = 0; break; case SIGCHLD: case SIGHUP: sig = 0; break; case SIGSEGV: case SIGIO: case SIGALRM: case SIGVTALRM: case SIGFPE: case SIGBUS: case SIGILL: case SIGWINCH: default: tracing = 0; break; } set_tracing(task, tracing); if(!tracing && old_tracing) arch_enter_kernel(task, pid); if(!tracing && (debugger_pid != -1) && (sig != 0) && (sig != SIGALRM) && (sig != SIGVTALRM) && (sig != SIGSEGV) && (sig != SIGTRAP) && (sig != SIGUSR2) && (sig != SIGIO) && (sig != SIGFPE)){ child_signal(pid, status); continue; } if(tracing){ if(singlestepping_tt(task)) cont_type = PTRACE_SINGLESTEP; else cont_type = PTRACE_SYSCALL; } else cont_type = PTRACE_CONT; if((cont_type == PTRACE_CONT) && (debugger_pid != -1) && strace) cont_type = PTRACE_SYSCALL; if(ptrace(cont_type, pid, 0, sig) != 0){ tracer_panic("ptrace failed to continue " "process - errno = %d\n", errno); } } }
/* some of this code is based on /usr/bin/time source code */ void print_stats(struct timeval *start, struct timeval *end, struct rusage *ru, int status) { unsigned long r; /* Elapsed real milliseconds. */ unsigned long v; /* Elapsed virtual (CPU) milliseconds. */ end->tv_sec -= start->tv_sec; if (end->tv_usec < start->tv_usec) { /* Manually carry a one from the seconds field. */ end->tv_usec += 1000000; --end->tv_sec; } end->tv_usec -= start->tv_usec; if (WIFSTOPPED (status)) { fprintf(FP, "Command stopped by signal %d\n", WSTOPSIG (status)); } else if (WIFSIGNALED (status)) { fprintf(FP, "Command terminated by signal %d\n", WTERMSIG (status)); } else if (WIFEXITED (status) && WEXITSTATUS (status)) { fprintf(FP, "Command exited with non-zero status %d\n", WEXITSTATUS (status)); } /* Convert all times to milliseconds. Occasionally, one of these values comes out as zero. Dividing by zero causes problems, so we first check the time value. If it is zero, then we take `evasive action' instead of calculating a value. */ r = end->tv_sec * 1000 + end->tv_usec / 1000; v = ru->ru_utime.tv_sec * 1000 + ru->ru_utime.TV_MSEC + ru->ru_stime.tv_sec * 1000 + ru->ru_stime.TV_MSEC; /* Elapsed real (wall clock) time. */ if (end->tv_sec >= 3600) { /* One hour -> h:m:s. */ fprintf(FP, "%ld:%02ld:%02ldelapsed ", end->tv_sec / 3600, (end->tv_sec % 3600) / 60, end->tv_sec % 60); } else { fprintf(FP, "%ld:%02ld.%02ldelapsed ", /* -> m:s. */ end->tv_sec / 60, end->tv_sec % 60, end->tv_usec / 10000); } /* % cpu is (total cpu time)/(elapsed time). */ if (r > 0) fprintf(FP, "%lu%%CPU ", (v * 100 / r)); else fprintf(FP, "?%%CPU "); fprintf(FP, "%ld.%02lduser ", ru->ru_utime.tv_sec, ru->ru_utime.TV_MSEC / 10); fprintf(FP, "%ld.%02ldsystem ", ru->ru_stime.tv_sec, ru->ru_stime.TV_MSEC / 10); fprintf(FP, "(%ldmajor+%ldminor)pagefaults %ldswaps\n", ru->ru_majflt,/* Major page faults. */ ru->ru_minflt,/* Minor page faults. */ ru->ru_nswap); /* times swapped out */ fprintf(FP, "(%lu tot, %lu RSS, %lu data, %lu stk, %lu exe, %lu lib)k\n", vmstats.VmSize, vmstats.VmRSS, vmstats.VmData, vmstats.VmStk, vmstats.VmExe, vmstats.VmLib); #if VERBOSE fprintf(FP, "Memory usage:\n"); fprintf(FP, "\tVmSize: %d kB\n", vmstats.VmSize); fprintf(FP, "\tVmLck: %d kB\n", vmstats.VmLck); fprintf(FP, "\tVmRSS: %d kB\n", vmstats.VmRSS); fprintf(FP, "\tVmData: %d kB\n", vmstats.VmData); fprintf(FP, "\tVmStk: %d kB\n", vmstats.VmStk); fprintf(FP, "\tVmExe: %d kB\n", vmstats.VmExe); fprintf(FP, "\tVmLib: %d kB\n", vmstats.VmLib); #endif }
/* Wait for a subprocess to finish. Return its exit code. If it didn't terminate correctly, exit if exit_on_error is true, otherwise return 127. */ int wait_subprocess (pid_t child, const char *progname, bool null_stderr, bool slave_process, bool exit_on_error) { #if HAVE_WAITID && defined WNOWAIT && 0 /* Commented out because waitid() with WNOWAIT doesn't work: On Solaris 7 and OSF/1 4.0, it returns -1 and sets errno = ECHILD, and on HP-UX 10.20 it just hangs. */ /* Use of waitid() with WNOWAIT avoids a race condition: If slave_process is true, and this process sleeps a very long time between the return from waitpid() and the execution of unregister_slave_subprocess(), and meanwhile another process acquires the same PID as child, and then - still before unregister_slave_subprocess() - this process gets a fatal signal, it would kill the other totally unrelated process. */ siginfo_t info; for (;;) { if (waitid (P_PID, child, &info, slave_process ? WNOWAIT : 0) < 0) { # ifdef EINTR if (errno == EINTR) continue; # endif if (exit_on_error || !null_stderr) error (exit_on_error ? EXIT_FAILURE : 0, errno, _("%s subprocess"), progname); return 127; } /* info.si_code is set to one of CLD_EXITED, CLD_KILLED, CLD_DUMPED, CLD_TRAPPED, CLD_STOPPED, CLD_CONTINUED. Loop until the program terminates. */ if (info.si_code == CLD_EXITED || info.si_code == CLD_KILLED || info.si_code == CLD_DUMPED) break; } /* The child process has exited or was signalled. */ if (slave_process) { /* Unregister the child from the list of slave subprocesses, so that later, when we exit, we don't kill a totally unrelated process which may have acquired the same pid. */ unregister_slave_subprocess (child); /* Now remove the zombie from the process list. */ for (;;) { if (waitid (P_PID, child, &info, 0) < 0) { # ifdef EINTR if (errno == EINTR) continue; # endif if (exit_on_error || !null_stderr) error (exit_on_error ? EXIT_FAILURE : 0, errno, _("%s subprocess"), progname); return 127; } break; } } switch (info.si_code) { case CLD_KILLED: case CLD_DUMPED: if (exit_on_error || !null_stderr) error (exit_on_error ? EXIT_FAILURE : 0, 0, _("%s subprocess got fatal signal %d"), progname, info.si_status); return 127; case CLD_EXITED: if (info.si_status == 127) { if (exit_on_error || !null_stderr) error (exit_on_error ? EXIT_FAILURE : 0, 0, _("%s subprocess failed"), progname); return 127; } return info.si_status; default: abort (); } #else /* waitpid() is just as portable as wait() nowadays. */ WAIT_T status; *(int *) &status = 0; for (;;) { int result = waitpid (child, &status, 0); if (result != child) { # ifdef EINTR if (errno == EINTR) continue; # endif # if 0 /* defined ECHILD */ if (errno == ECHILD) { /* Child process nonexistent?! Assume it terminated successfully. */ *(int *) &status = 0; break; } # endif if (exit_on_error || !null_stderr) error (exit_on_error ? EXIT_FAILURE : 0, errno, _("%s subprocess"), progname); return 127; } /* One of WIFSIGNALED (status), WIFEXITED (status), WIFSTOPPED (status) must always be true. Loop until the program terminates. */ if (!WIFSTOPPED (status)) break; } /* The child process has exited or was signalled. */ if (slave_process) /* Unregister the child from the list of slave subprocesses, so that later, when we exit, we don't kill a totally unrelated process which may have acquired the same pid. */ unregister_slave_subprocess (child); if (WIFSIGNALED (status)) { if (exit_on_error || !null_stderr) error (exit_on_error ? EXIT_FAILURE : 0, 0, _("%s subprocess got fatal signal %d"), progname, (int) WTERMSIG (status)); return 127; } if (WEXITSTATUS (status) == 127) { if (exit_on_error || !null_stderr) error (exit_on_error ? EXIT_FAILURE : 0, 0, _("%s subprocess failed"), progname); return 127; } return WEXITSTATUS (status); #endif }
/****************************************************************************** * * * Function: zbx_waitpid * * * * Purpose: this function waits for process to change state * * * * Parameters: pid - [IN] child process PID * * * * Return value: on success, PID is returned. On error, * * -1 is returned, and errno is set appropriately * * * * Author: Alexander Vladishev * * * ******************************************************************************/ static int zbx_waitpid(pid_t pid) { const char *__function_name = "zbx_waitpid"; int rc, status; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); do { #ifdef WCONTINUED static int wcontinued = WCONTINUED; retry: if (-1 == (rc = waitpid(pid, &status, WUNTRACED | wcontinued))) { if (EINVAL == errno && 0 != wcontinued) { wcontinued = 0; goto retry; } #else if (-1 == (rc = waitpid(pid, &status, WUNTRACED))) { #endif zabbix_log(LOG_LEVEL_DEBUG, "%s() waitpid failure: %s", __function_name, zbx_strerror(errno)); goto exit; } if (WIFEXITED(status)) zabbix_log(LOG_LEVEL_DEBUG, "%s() exited, status:%d", __function_name, WEXITSTATUS(status)); else if (WIFSIGNALED(status)) zabbix_log(LOG_LEVEL_DEBUG, "%s() killed by signal %d", __function_name, WTERMSIG(status)); else if (WIFSTOPPED(status)) zabbix_log(LOG_LEVEL_DEBUG, "%s() stopped by signal %d", __function_name, WSTOPSIG(status)); #ifdef WIFCONTINUED else if (WIFCONTINUED(status)) zabbix_log(LOG_LEVEL_DEBUG, "%s() continued", __function_name); #endif } while (!WIFEXITED(status) && !WIFSIGNALED(status)); exit: zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%d", __function_name, rc); return rc; } #endif /* _WINDOWS */ /****************************************************************************** * * * Function: zbx_execute * * * * Purpose: this function executes a script and returns result from stdout * * * * Parameters: command - [IN] command for execution * * buffer - [OUT] buffer for output, if NULL - ignored * * error - [OUT] error string if function fails * * max_error_len - [IN] length of error buffer * * * * Return value: SUCCEED if processed successfully, TIMEOUT_ERROR if * * timeout occurred or FAIL otherwise * * * * Author: Alexander Vladishev * * * ******************************************************************************/ int zbx_execute(const char *command, char **buffer, char *error, size_t max_error_len, int timeout) { size_t buf_size = PIPE_BUFFER_SIZE, offset = 0; int ret = FAIL; #ifdef _WINDOWS STARTUPINFO si; PROCESS_INFORMATION pi; SECURITY_ATTRIBUTES sa; HANDLE job = NULL, hWrite = NULL, hRead = NULL; char *cmd = NULL; wchar_t *wcmd = NULL; struct _timeb start_time, current_time; #else pid_t pid; int fd; #endif *error = '\0'; if (NULL != buffer) { *buffer = zbx_realloc(*buffer, buf_size); **buffer = '\0'; } #ifdef _WINDOWS /* set the bInheritHandle flag so pipe handles are inherited */ sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.bInheritHandle = TRUE; sa.lpSecurityDescriptor = NULL; /* create a pipe for the child process's STDOUT */ if (0 == CreatePipe(&hRead, &hWrite, &sa, 0)) { zbx_snprintf(error, max_error_len, "unable to create a pipe: %s", strerror_from_system(GetLastError())); goto close; } /* create a new job where the script will be executed */ if (0 == (job = CreateJobObject(&sa, NULL))) { zbx_snprintf(error, max_error_len, "unable to create a job: %s", strerror_from_system(GetLastError())); goto close; } /* fill in process startup info structure */ memset(&si, 0, sizeof(STARTUPINFO)); si.cb = sizeof(STARTUPINFO); si.dwFlags = STARTF_USESTDHANDLES; si.hStdInput = GetStdHandle(STD_INPUT_HANDLE); si.hStdOutput = hWrite; si.hStdError = hWrite; /* use cmd command to support scripts */ cmd = zbx_dsprintf(cmd, "cmd /C \"%s\"", command); wcmd = zbx_utf8_to_unicode(cmd); /* create the new process */ if (0 == CreateProcess(NULL, wcmd, NULL, NULL, TRUE, CREATE_SUSPENDED, NULL, NULL, &si, &pi)) { zbx_snprintf(error, max_error_len, "unable to create process [%s]: %s", cmd, strerror_from_system(GetLastError())); goto close; } CloseHandle(hWrite); hWrite = NULL; /* assign the new process to the created job */ if (0 == AssignProcessToJobObject(job, pi.hProcess)) { zbx_snprintf(error, max_error_len, "unable to assign process [%s] to a job: %s", cmd, strerror_from_system(GetLastError())); if (0 == TerminateProcess(pi.hProcess, 0)) { zabbix_log(LOG_LEVEL_ERR, "failed to terminate [%s]: %s", cmd, strerror_from_system(GetLastError())); } } else if (-1 == ResumeThread(pi.hThread)) { zbx_snprintf(error, max_error_len, "unable to assign process [%s] to a job: %s", cmd, strerror_from_system(GetLastError())); } else ret = SUCCEED; if (FAIL == ret) goto close; _ftime(&start_time); timeout *= 1000; ret = zbx_read_from_pipe(hRead, buffer, &buf_size, &offset, timeout); if (TIMEOUT_ERROR != ret) { _ftime(¤t_time); if (0 < (timeout -= zbx_get_timediff_ms(&start_time, ¤t_time)) && WAIT_TIMEOUT == WaitForSingleObject(pi.hProcess, timeout)) { ret = TIMEOUT_ERROR; } } CloseHandle(pi.hProcess); CloseHandle(pi.hThread); close: if (NULL != job) { /* terminate the child process and it's childs */ if (0 == TerminateJobObject(job, 0)) zabbix_log(LOG_LEVEL_ERR, "failed to terminate job [%s]: %s", cmd, strerror_from_system(GetLastError())); CloseHandle(job); } if (NULL != hWrite) CloseHandle(hWrite); if (NULL != hRead) CloseHandle(hRead); zbx_free(cmd); zbx_free(wcmd); #else /* not _WINDOWS */ alarm(timeout); if (-1 != (fd = zbx_popen(&pid, command))) { int rc; char tmp_buf[PIPE_BUFFER_SIZE]; while (0 < (rc = read(fd, tmp_buf, sizeof(tmp_buf) - 1)) && MAX_EXECUTE_OUTPUT_LEN > offset + rc) { if (NULL != buffer) { tmp_buf[rc] = '\0'; zbx_strcpy_alloc(buffer, &buf_size, &offset, tmp_buf); } } close(fd); if (-1 == rc || -1 == zbx_waitpid(pid)) { if (EINTR == errno) ret = TIMEOUT_ERROR; else zbx_snprintf(error, max_error_len, "zbx_waitpid() failed: %s", zbx_strerror(errno)); /* kill the whole process group, pid must be the leader */ if (-1 == kill(-pid, SIGTERM)) zabbix_log(LOG_LEVEL_ERR, "failed to kill [%s]: %s", command, zbx_strerror(errno)); zbx_waitpid(pid); } else if (MAX_EXECUTE_OUTPUT_LEN <= offset + rc) { zabbix_log(LOG_LEVEL_ERR, "command output exceeded limit of %d KB", MAX_EXECUTE_OUTPUT_LEN / ZBX_KIBIBYTE); } else ret = SUCCEED; } else zbx_strlcpy(error, zbx_strerror(errno), max_error_len); alarm(0); #endif /* _WINDOWS */ if (TIMEOUT_ERROR == ret) zbx_strlcpy(error, "Timeout while executing a shell script.", max_error_len); else if ('\0' != *error) zabbix_log(LOG_LEVEL_WARNING, "%s", error); if (SUCCEED != ret && NULL != buffer) zbx_free(*buffer); return ret; }
/* exit codes: 0 = ok, 1 = invocation error, 3 = internal error */ int main(int argc, char *argv[]) { int envIdx = ArgEnv; int errNo; int chldPid; int chldStatus; int chldPipe[2]; 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); } sau.sun_family = AF_UNIX; strcpy(sau.sun_path, argv[ArgSocket]); 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; } /* 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 failed"); 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 for (envIdx = ArgEnv; *argv[envIdx]; ++envIdx) ; if (envIdx != ArgEnv) { argv[envIdx] = 0; environ = argv + ArgEnv; } ++envIdx; execvp(argv[envIdx], argv + envIdx); /* 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; } }
static void l2tpd_watch_cb (GPid pid, gint status, gpointer user_data) { NML2tpPlugin *plugin = NM_L2TP_PLUGIN (user_data); NML2tpPluginPrivate *priv = NM_L2TP_PLUGIN_GET_PRIVATE (plugin); guint error = 0; pid_t my_pid = getpid (); char *filename; if (WIFEXITED (status)) { error = WEXITSTATUS (status); if (error != 0) g_warning (_("xl2tpd exited with error code %d"), error); } else if (WIFSTOPPED (status)) g_warning (_("xl2tpd stopped unexpectedly with signal %d"), WSTOPSIG (status)); else if (WIFSIGNALED (status)) g_warning (_("xl2tpd died with signal %d"), WTERMSIG (status)); else g_warning (_("xl2tpd died from an unknown cause")); /* Reap child if needed. */ waitpid (priv->pid_l2tpd, NULL, WNOHANG); priv->pid_l2tpd = 0; if(priv->ipsec_up) { nm_l2tp_stop_ipsec(); } /* Cleaning up config files */ filename = g_strdup_printf ("/var/run/nm-xl2tpd.conf.%d", my_pid); unlink(filename); g_free(filename); filename = g_strdup_printf ("/var/run/nm-ppp-options.xl2tpd.%d", my_pid); unlink(filename); g_free(filename); filename = g_strdup_printf ("/var/run/nm-ipsec-l2tp.%d/ipsec.conf", my_pid); // unlink(filename); g_free(filename); filename = g_strdup_printf ("/var/run/nm-ipsec-l2tp.%d/ipsec.secrets", my_pid); // unlink(filename); g_free(filename); filename = g_strdup_printf ("/var/run/nm-ipsec-l2tp.%d", my_pid); rmdir(filename); g_free(filename); /* Must be after data->state is set since signals use data->state */ switch (error) { case 16: /* hangup */ // FIXME: better failure reason nm_vpn_plugin_failure (NM_VPN_PLUGIN (plugin), NM_VPN_PLUGIN_FAILURE_CONNECT_FAILED); break; case 2: /* Couldn't log in due to bad user/pass */ nm_vpn_plugin_failure (NM_VPN_PLUGIN (plugin), NM_VPN_PLUGIN_FAILURE_LOGIN_FAILED); break; case 1: /* Other error (couldn't bind to address, etc) */ nm_vpn_plugin_failure (NM_VPN_PLUGIN (plugin), NM_VPN_PLUGIN_FAILURE_CONNECT_FAILED); break; default: break; } nm_vpn_plugin_set_state (NM_VPN_PLUGIN (plugin), NM_VPN_SERVICE_STATE_STOPPED); }
//-------------------------------------------------------------------------- void linux_debmod_t::tdb_update_threads(void) { if ( ta != NULL ) { thrinfovec_t newlist; td_err_e err = td_ta_thr_iter(ta, update_threads_cb, &newlist, TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY, TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS); COMPLAIN_IF_FAILED("td_ta_thr_iter", err); if ( err != TD_OK ) return; // generate THREAD_EXIT events for ( threads_t::iterator p=threads.begin(); p != threads.end(); ++p ) { int i; int tid = p->first; for ( i=0; i < newlist.size(); i++ ) if ( newlist[i].ti_lid == tid ) break; if ( i == newlist.size() ) // not found { debug_event_t ev; ev.eid = THREAD_EXIT; ev.pid = process_handle; ev.tid = tid; ev.ea = BADADDR; ev.handled = true; ev.exit_code = 0; // ??? enqueue_event(ev, IN_BACK); } } // generate THREAD_START events for ( int i=0; i < newlist.size(); i++ ) { int tid = newlist[i].ti_lid; // display_thrinfo(tid); threads_t::iterator p = threads.find(tid); if ( p == threads.end() ) // not found { debug_event_t ev; ev.eid = THREAD_START; ev.pid = process_handle; ev.tid = tid; ev.ea = birth_bpt.bpt_addr; // just to show something ev.handled = true; add_thread(tid); enqueue_event(ev, IN_FRONT); // attach to the thread and make is ready for debugging qptrace(PTRACE_ATTACH, tid, 0, 0); int status; int tid2 = waitpid(tid, &status, __WCLONE); // (must succeed) consume SIGSTOP QASSERT(tid2 != -1 && WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP); get_thread(tid)->waiting_sigstop = false; } get_thread(tid)->thr = newlist[i].th_p; } } }
void run_phase (phases_t phase, char *name, string_list_t *args) { char **argv; int argc = 1; string_item_t *p; char *output = NULL; char *input = NULL; boolean save_stderr = FALSE; int fdin, fdout; int forkpid; int waitpid; int waitstatus; int termsig; int num_maps; char *rld_path, *absoft_path; struct stat stat_buf; const boolean uses_message_system = (phase == P_f90_fe || phase == P_f90_cpp || phase == P_cppf90_fe); #if defined(__APPLE__) // pass -Wa,-W to assembler so we ignore unknowns int hack_as_W = 0; if (strcmp(name, "/usr/bin/gcc") == 0) { hack_as_W = 1; argc++; } #endif if (show_flag) { /* echo the command */ fprintf(stderr, "%s ", name); print_string_list(stderr, args); } if (!execute_flag) return; if (time_flag) init_time(); /* copy arg_list to argv format that exec wants */ for (p = args->head; p != NULL; p=p->next) { //bug# 581, bug #932, bug #1049 if (p->name == NULL) continue; argc++; } argv = (char **) malloc((argc+1)*sizeof(char*)); argv[0] = name; for (argc = 1, p = args->head; p != NULL; argc++, p=p->next) { //bug# 581, bug #932 if (p->name[0] == '\0') { argc--; continue; } /* don't put redirection in arg list */ if (strcmp(p->name, "<") == 0) { /* has input file */ input = p->next->name; break; } else if (strcmp(p->name, ">") == 0) { /* has output file */ output = p->next->name; break; } else if (strcmp(p->name, ">&") == 0) { /* has error output file */ output = p->next->name; save_stderr = TRUE; break; } argv[argc] = p->name; } #if defined(__APPLE__) if (hack_as_W) { #ifndef Is_True_On argv[argc++] = ""; // "-Wa,-W"; #endif } #endif argv[argc] = NULL; /* fork a process */ forkpid = fork(); if (forkpid == -1) { error("no more processes"); cleanup (); do_exit (RC_SYSTEM_ERROR); /* NOTREACHED */ } if (forkpid == 0) { char *my_path, *l_path, *l32_path, *nls_path, *env_path; /* child */ /* if we want memory stats, we have to wait for parent to connect to our /proc */ if (input != NULL) { if ((fdin = open (input, O_RDONLY)) == -1) { error ("cannot open input file %s", input); cleanup (); do_exit (RC_SYSTEM_ERROR); /* NOTREACHED */ } dup2 (fdin, fileno(stdin)); } if (output != NULL) { if ((fdout = creat (output, 0666)) == -1) { error ("cannot create output file %s", output); cleanup (); do_exit (RC_SYSTEM_ERROR); /* NOTREACHED */ } if (save_stderr) { dup2 (fdout, fileno(stderr)); } else { dup2 (fdout, fileno(stdout)); } } my_path = get_binutils_lib_path(); rld_path = get_phase_ld_library_path (phase); absoft_path = get_absoft_ld_library_path (phase); if (absoft_path != 0) asprintf(&my_path, "%s:%s", my_path, absoft_path); if (rld_path != 0) asprintf(&my_path, "%s:%s", my_path, rld_path); l_path = l32_path = my_path; if (ld_library_path) asprintf(&l_path, "%s:%s", my_path, ld_library_path); if (ld_libraryn32_path) asprintf(&l32_path, "%s:%s", my_path, ld_libraryn32_path); my_putenv("LD_LIBRARY_PATH", l_path); my_putenv("LD_LIBRARYN32_PATH", l32_path); // Set up NLSPATH, for the Fortran front end. nls_path = getenv("NLSPATH"); env_path = get_phase_dir(P_f90_fe); if (nls_path) { my_putenv("NLSPATH", "%s:%s/%%N.cat", nls_path, env_path); } else { my_putenv("NLSPATH", "%s/%%N.cat", env_path); } if (uses_message_system && getenv("ORIG_CMD_NAME") == NULL) my_putenv("ORIG_CMD_NAME", "%s", program_name); if (phase == P_f90_fe) { char *root; char *modulepath; int len; char *new_env; char *env_name = "FORTRAN_SYSTEM_MODULES="; char *env_val = "/usr/lib/f90modules"; root = getenv("TOOLROOT"); if (root != NULL) { len = strlen(env_val) + strlen(root) +3 + strlen(env_val); new_env = alloca(len); sprintf(new_env,"%s/%s:%s",root,env_val,env_val); env_val = new_env; } modulepath = string_copy(getenv("FORTRAN_SYSTEM_MODULES")); if (modulepath != NULL) { /* Append env_val to FORTRAN_SYSTEM_MODULES */ if (modulepath[strlen(modulepath)-1] == ':') { /* Just append env_val */ len = strlen(modulepath) + strlen(env_val) + 1; new_env = alloca(len); sprintf(new_env,"%s%s",modulepath,env_val); } else { /* append :env_val */ len = strlen(modulepath) + strlen(env_val) + 2; new_env = alloca(len); sprintf(new_env,"%s:%s",modulepath,env_val); } env_val = new_env; } my_putenv ("FORTRAN_SYSTEM_MODULES", "%s", env_val); } /* need to setenv COMPILER_PATH for collect to find ld */ my_putenv ("COMPILER_PATH", "%s", get_phase_dir(P_collect)); /* Tell IPA where to find the driver. */ #if defined(ABSOFT_EXTENSIONS) my_putenv ("COMPILER_BIN", "%s/" PSC_NAME_PREFIX "f90", get_executable_dir()); #else my_putenv ("COMPILER_BIN", "%s/" PSC_NAME_PREFIX "cc-" PSC_FULL_VERSION, get_executable_dir()); #endif my_execv(name, argv); } else { /* parent */ int procid; /* id of the /proc file */ while ((waitpid = wait (&waitstatus)) != forkpid) { if (waitpid == -1) { error("bad return from wait"); cleanup(); do_exit(RC_SYSTEM_ERROR); /* NOTREACHED */ } } if (time_flag) print_time(name); if (WIFSTOPPED(waitstatus)) { termsig = WSTOPSIG(waitstatus); error("STOPPED signal received from %s", name); cleanup(); do_exit(RC_SYSTEM_ERROR); /* NOTREACHED */ } else if (WIFEXITED(waitstatus)) { int status = WEXITSTATUS(waitstatus); extern int inline_t; boolean internal_err = FALSE; boolean user_err = FALSE; if (phase == P_prof) { /* Make sure the .cfb files were created before changing the STATUS to OKAY */ if (prof_file != NULL) { if (!(stat(fb_file, &stat_buf) != 0 && errno == ENOENT)) status = RC_OKAY; } else { internal_error("No count file was specified for a prof run"); perror(program_name); } } if (phase == P_f90_fe && keep_listing) { char *cif_file; cif_file = construct_given_name( drop_path(source_file), "T", TRUE); if (!(stat(cif_file, &stat_buf) != 0 && errno == ENOENT)) f90_fe_status = status; f90_fe_name = string_copy(name); /* Change the status to OKAY so that we can * execute the lister on the cif_file; we will * take appropriate action on this status once * the lister has finished executing. See below. */ status = RC_OKAY; } if (phase == P_lister) { if (status == RC_OKAY && f90_fe_status != RC_OKAY) { /* We had encountered an error in the F90_fe phase * but we ignored it so that we could execute the * lister on the cif file; we need to switch the * status to the status we received from F90_fe * and use the name of the F90_fe_phase, so that * we can issue a correct error message. */ status = f90_fe_status; name = string_copy(f90_fe_name); /* Reset f90_fe_status to OKAY for any further * compilations on other source files. */ f90_fe_status = RC_OKAY; } } switch (status) { case RC_OKAY: if (inline_t == UNDEFINED && is_matching_phase( get_phase_mask(phase), P_any_fe) ) { inline_t = FALSE; } break; case RC_NEED_INLINER: if (inline_t == UNDEFINED && is_matching_phase( get_phase_mask(phase), P_any_fe) ) { inline_t = TRUE; } /* completed successfully */ break; case RC_USER_ERROR: case RC_NORECOVER_USER_ERROR: case RC_SYSTEM_ERROR: case RC_GCC_ERROR: user_err = TRUE; break; case RC_OVERFLOW_ERROR: if (!ran_twice && phase == P_be) { /* try recompiling with larger limits */ ran_twice = TRUE; add_string (args, "-TENV:long_eh_offsets"); add_string (args, "-TENV:large_stack"); run_phase (phase, name, args); return; } internal_err = TRUE; break; case RC_INTERNAL_ERROR: internal_err = TRUE; break; default: internal_err = TRUE; break; } if (internal_err) { if (phase == P_ld || phase == P_ldplus || #ifdef KEY phase == P_gas || // bug 4846 #endif phase == P_gcpp || phase == P_gcpp_plus) { if (phase == P_gas) internal_error_occurred = 1; log_error("%s returned non-zero status %d", name, status); nomsg_error(status); } else { internal_error("%s returned non-zero status %d", name, status); } } else if (user_err) { /* assume phase will print diagnostics */ if (phase == P_c_gfe || phase == P_cplus_gfe) { nomsg_error(RC_INTERNAL_ERROR); } else if (!show_flag || save_stderr) { nomsg_error(RC_USER_ERROR); } else { error("%s returned non-zero status %d", name, status); } } ran_twice = FALSE; return; } else if(WIFSIGNALED(waitstatus)){ termsig = WTERMSIG(waitstatus); switch (termsig) { case SIGHUP: case SIGINT: case SIGQUIT: case SIGKILL: case SIGTERM: error("%s died due to signal %d", name, termsig); break; default: internal_error("%s died due to signal %d", name, termsig); break; } #ifndef __CYGWIN__ if(waitstatus & WCOREFLAG) { error("core dumped"); } #endif if (termsig == SIGKILL) { error("Probably caused by running out of swap space -- check %s", LOGFILE); } cleanup(); do_exit(RC_SYSTEM_ERROR); } else { /* cannot happen, I think! */ internal_error("driver exec'ing is confused"); return; } } }
/** Main loop for the Event Dispatcher process. * */ int dispatcher_main_loop(void) { struct pollfd poll_fds[3+MAX_AS_NR],*poll_tmp; int clean_index,i,j,k,fd,poll_events=0,socks[2],chld_status; int as_nr,unc_as_nr; pid_t chld; struct timeval last_ping,now; struct as_entry *as; sig_flag=0; is_dispatcher=1; as_nr=0; timerclear(&last_ping); timerclear(&now); signal(SIGCHLD,seas_sighandler); signal(SIGTERM,seas_sighandler); signal(SIGUSR1,seas_sighandler); signal(SIGINT, seas_sighandler); signal(SIGKILL,seas_sighandler); strcpy(whoami,"Seas Event Dispatcher process"); /*I set process_no to -1 because otherwise, the logging process confuses this process with another from SER * (see LM_*() and dprint() and my_pid())*/ process_no = -1; if(open_server_sockets(seas_listen_ip,seas_listen_port,socks)==-1){ LM_ERR("unable to open server sockets on dispatcher\n"); return -1; } for(i=0;i<2;i++){ poll_fds[i].fd=socks[i]; poll_fds[i].revents=0; poll_fds[i].events=POLLIN; } poll_fds[2].fd=read_pipe; poll_fds[2].revents=0; poll_fds[2].events=POLLIN;/*pollhup ?*/ poll_events=0; unc_as_nr=0; if(use_ha) spawn_pinger(); while(1){ if(sig_flag==SIGCHLD){ while ((chld=waitpid( -1, &chld_status, WNOHANG ))>0) { if (WIFEXITED(chld_status)){ LM_INFO("child process %d exited normally, status=%d\n", chld,WEXITSTATUS(chld_status)); }else if (WIFSIGNALED(chld_status)) { LM_INFO("child process %d exited by a signal %d\n", chld,WTERMSIG(chld_status)); }else if (WIFSTOPPED(chld_status)) LM_INFO("child process %d stopped by a signal %d\n", chld,WSTOPSIG(chld_status)); for (as=as_list;as;as=as->next) { if(as->type!=AS_TYPE) continue; if(as->u.as.action_pid==chld){ for(i=0;i<as_nr && ((poll_fds[3+i].fd)!=(as->u.as.event_fd));i++) ; if(i==as_nr){ LM_ERR("Either the pinger has died or BUG found..\n"); continue; } /*overwrite the obsolete 'i' position with the next position*/ for(j=3+i;j<(as_nr+unc_as_nr+3-1);i++){ poll_fds[j].fd=poll_fds[j+1].fd; poll_fds[j].events=poll_fds[j+1].events; poll_fds[j].revents=poll_fds[j+1].revents; } close(as->u.as.event_fd);/*close the socket fd*/ if (as->u.as.ev_buffer.s) { pkg_free(as->u.as.ev_buffer.s); as->u.as.ev_buffer.s=(char *)0; as->u.as.ev_buffer.len=0; } as->u.as.event_fd=as->u.as.action_fd=-1; as->connected=0; destroy_pingtable(&as->u.as.jain_pings); destroy_pingtable(&as->u.as.servlet_pings); as_nr--; LM_WARN("client [%.*s] leaving (Action Dispatcher Process died !)\n", as->name.len,as->name.s); break; }/*if(action_pid==chld)*/ }/*for(as=as_list;as;as=as->next)*/ }/*while(waitpid(-1)>0)*/ }else if (sig_flag) { LM_WARN("received signal != sigchld(%d)\n",sig_flag); } sig_flag=0; clean_index=0; LM_INFO("polling [2 ServSock] [1 pipe] [%d App Servers]" " [%d Uncomplete AS]\n",as_nr,unc_as_nr); poll_events = poll(poll_fds,3+unc_as_nr+as_nr,-1); if (poll_events == -1) { if(errno==EINTR){ /*handle the case a child has died. * It will be done in the next iteration in if(seas_sigchld_received)*/ continue; } if(errno==EBADF){ LM_ERR("invalid file descriptor pased to poll (%s)\n", strerror(errno)); return -1;/*??*/ } /* errors */ LM_ERR("poll'ing:%s\n",strerror(errno)); poll_events=0; continue; } else if (poll_events == 0) {/*timeout*/ continue; } else {/*there are events !*/ /*handle connections from server sockets*/ for(i=0;i<2;i++){ if(poll_fds[i].revents) poll_events--; if(poll_fds[i].revents & POLLIN){ poll_fds[i].revents &= (~POLLIN); if((fd=new_as_connect(socks[i],i==0?'e':'a'))>=0){ poll_tmp=&poll_fds[3+as_nr+unc_as_nr]; poll_tmp->fd=fd; poll_tmp->events=POLLIN|POLLHUP; unc_as_nr++; LM_DBG("Have new %s client\n",i==0?"event":"action"); }else{ LM_ERR("accepting connection from AS\n"); } } } /*handle data from pipe*/ if(poll_fds[2].revents & POLLIN){ poll_fds[2].revents &= (~POLLIN); poll_events--; if(dispatch_relay()<0){ LM_ERR("dispatch_relay returned -1" "should clean-up table\n"); } } /*now handle receive data from completed AS*/ clean_index=0; LM_DBG("Scanning data from %d AS\n",as_nr); for(i=0;(i<as_nr) && poll_events;i++){ clean_index=0; poll_tmp=&poll_fds[3+i]; if(poll_tmp->revents) poll_events--; if(poll_tmp->revents & POLLIN){ LM_DBG("POLLIN found in AS #%i\n",i); poll_tmp->revents &= (~POLLIN); switch(handle_as_data(poll_tmp->fd)){ case -2:/*read returned 0 bytes, an AS client is leaving*/ clean_index=1; break; case -1:/*shouldnt happen*/ LM_ERR("reading from AS socket\n"); break; case 0:/* event_response received and processed*/ break; default: LM_WARN("unknown return type from handle_as_data\n"); } } if(clean_index || (poll_tmp->revents & POLLHUP)){ LM_DBG("POLHUP or read==0 found in %i AS \n",i); clean_index=0; poll_tmp->revents = 0; for(as=as_list;as;as=as->next){ if(as->type==CLUSTER_TYPE) continue; if(as->connected && (as->u.as.event_fd == poll_tmp->fd)){ close(poll_tmp->fd);/*close the socket fd*/ /*TODO we should send a signal to the Action Dispatcher !!!*/ as->connected=0; as_nr--; /*overwrite the obsolete 'i' position with the next position*/ for(k=i;k<(as_nr+unc_as_nr);k++){ j=3+k; poll_fds[j].fd=poll_fds[j+1].fd; poll_fds[j].events=poll_fds[j+1].events; poll_fds[j].revents=poll_fds[j+1].revents; } --i; LM_WARN("client %.*s leaving !!!\n",as->name.len,as->name.s); break; } } if (!as) { LM_ERR("the leaving client was not found in the as_list\n"); } } } /*now handle data sent from uncompleted AS*/ LM_DBG("Scanning data from %d uncomplete AS \n",unc_as_nr); clean_index=0; for(i=0;i<unc_as_nr && poll_events;i++){ poll_tmp=&poll_fds[3+as_nr+i]; if(poll_tmp->revents) poll_events--; if(poll_tmp->revents & POLLIN){ LM_DBG("POLLIN found in %d uncomplete AS \n",i); poll_tmp->revents &= (~POLLIN); fd=handle_unc_as_data(poll_tmp->fd); if(fd>0){ /* there's a new AS, push the uncomplete poll_fds up and set the AS */ for(k=i;k>0;k--){ j=3+as_nr+k; poll_fds[j].fd=poll_fds[j-1].fd; poll_fds[j].events=poll_fds[j-1].events; poll_fds[j].revents=poll_fds[j-1].revents; } poll_fds[3+as_nr].fd=fd; poll_fds[3+as_nr].events=POLLIN|POLLHUP; poll_fds[3+as_nr].revents=0; as_nr++;/*not very sure if this is thread-safe*/ unc_as_nr--; }else if(fd<=0){/* pull the upper set of uncomplete AS down and take this one out*/ poll_tmp->revents=0; for(k=i;k<(unc_as_nr-1);k++){ j=3+as_nr+k; poll_fds[j].fd=poll_fds[j+1].fd; poll_fds[j].events=poll_fds[j+1].events; poll_fds[j].revents=poll_fds[j+1].revents; } unc_as_nr--; /** we decrement i so that pulling down the upper part of the unc_as array so that * it doesn't affect our for loop */ i--; } } if(poll_tmp->revents & POLLHUP){ LM_DBG("POLLHUP found in %d uncomplete AS \n",i); close(poll_tmp->fd); for(k=i;k<(unc_as_nr-1);k++){ j=3+as_nr+k; poll_fds[j].fd=poll_fds[j+1].fd; poll_fds[j].events=poll_fds[j+1].events; poll_fds[j].revents=poll_fds[j+1].revents; } unc_as_nr--; i--; poll_tmp->revents = 0; } }/*for*/ }/*else ...(poll_events>0)*/ }/*while(1)*/ }
pid_t waitpid( pid_t pid, /* The pid to wait on. Must be -1 or greater * than zero. */ int *statusPtr, /* Where to store wait status for the * process. */ int options) /* OR'ed combination of WNOHANG and * WUNTRACED. */ { register WaitInfo *waitPtr, *prevPtr; pid_t result; WAIT_STATUS_TYPE status; if ((pid < -1) || (pid == 0)) { errno = EINVAL; return -1; } /* * See if there's a suitable process that has already stopped or exited. * If so, remove it from the list of exited processes and return its * information. */ for (waitPtr = deadList, prevPtr = NULL; waitPtr != NULL; prevPtr = waitPtr, waitPtr = waitPtr->nextPtr) { if ((pid != waitPtr->pid) && (pid != -1)) { continue; } if (!(options & WUNTRACED) && (WIFSTOPPED(waitPtr->status))) { continue; } result = waitPtr->pid; *statusPtr = *((int *) &waitPtr->status); if (prevPtr == NULL) { deadList = waitPtr->nextPtr; } else { prevPtr->nextPtr = waitPtr->nextPtr; } ckfree((char *) waitPtr); return result; } /* * Wait for any process to stop or exit. If it's an acceptable one then * return it to the caller; otherwise store information about it in the * list of exited processes and try again. On systems that have only wait * but not wait3, there are several situations we can't handle, but we do * the best we can (e.g. can still handle some combinations of options by * invoking wait instead of wait3). */ while (1) { #if NO_WAIT3 if (options & WNOHANG) { return 0; } if (options != 0) { errno = EINVAL; return -1; } result = wait(&status); #else result = wait3(&status, options, 0); #endif if ((result == -1) && (errno == EINTR)) { continue; } if (result <= 0) { return result; } if ((pid != result) && (pid != -1)) { goto saveInfo; } if (!(options & WUNTRACED) && (WIFSTOPPED(status))) { goto saveInfo; } *statusPtr = *((int *) &status); return result; /* * Can't return this info to caller. Save it in the list of stopped or * exited processes. Tricky point: first check for an existing entry * for the process and overwrite it if it exists (e.g. a previously * stopped process might now be dead). */ saveInfo: for (waitPtr = deadList; waitPtr != NULL; waitPtr = waitPtr->nextPtr) { if (waitPtr->pid == result) { waitPtr->status = status; goto waitAgain; } } waitPtr = (WaitInfo *) ckalloc(sizeof(WaitInfo)); waitPtr->pid = result; waitPtr->status = status; waitPtr->nextPtr = deadList; deadList = waitPtr; waitAgain: continue; } }
int main(int argc, char *argv[]) { char *line; char *prompt = "myshell>"; char *envPrompt = "DASH_PROMPT"; char *args[2048]; char *str; char *multiCmd[2048]; int i=0; int flag; int jobid; int code; int fd1,fd2; tcpid = getpgrp(); ObjectPtr myObj; NodePtr node; lst = createList(getKey,toString,freeObject); // Creating a List prompt = getenv(envPrompt); if(prompt == NULL) prompt = "myshell>"; using_history(); if(signal(SIGINT,signalHandling) == SIG_ERR){} if(signal(SIGTSTP,signalHandling) == SIG_ERR){} if(signal(SIGTTOU,SIG_IGN)==SIG_ERR){} if(signal(SIGCHLD,SIG_DFL)==SIG_ERR){} if((argc == 2) && (strcmp(argv[1],"-v")==0)) { printf("%s\n",svn_version()); exit(0); } code = sigsetjmp(env,TRUE); while ((line=readline(prompt))) // Reading Input { if(line==NULL) { printf("\n read line failed \n"); continue; } add_history(line); str = (char *)mymalloc(sizeof(char)*(strlen(line)+1)); strcpy(str,line); if(str[0] == '&' || str[0] == ';') { printf("dash: syntax error near unexpected token %c \n",str[0]); freeVar(line,str,args); continue; } while((pid = waitpid(-1,NULL,WNOHANG)) > 0) { node = search(lst,pid); ((ObjectPtr)(node->obj))->jobStatus = 0; printf("%s\n",(*toString)(node->obj)); removeNode(lst,node); } if(checkMultiCmd(str, multiCmd)== -1) continue; while(multiCmd[i]) { flag = searchAmp(multiCmd[i]); // Function to check if there is an '&' in the Command struct IORedirect *ior = tokenize(multiCmd[i],args); if((int)ior == -1) break; // Parsing the Command that needs to be executed if(exitLogout(multiCmd[i])) // Function to check Exit and Logout Commands { if(checkStoppedJobs()) { //memset(multiCmd,0,sizeof(multiCmd)); break; } else { freeVar(line,str,args); freeList(lst); memset(multiCmd,'\0',sizeof(multiCmd)); myfree(ior); exit(0); } } if(checkEOF(multiCmd[i])) // Function to check EOF { freeVar(line,str,args); memset(multiCmd,'\0',sizeof(multiCmd)); freeList(lst); myfree(ior); exit(0); } if(checkEmptyCmd(multiCmd[i])) // Function to Check if Enter Key is pressed break; if((strcmp(args[0],"cd")==0) && (flag == FALSE)) // Function to check if 'cd' command is used { chgDir(args); break; } if((strcmp(args[0],"jobs")==0) && (flag == FALSE)) // Function to check if 'jobs' command is used { jobsCmd(); break; } if(strcmp(args[0],"history")==0) { printHistory(args, str, flag); break; } if((strcmp(args[0],"bg") == 0) && (flag == FALSE)) { bgCmd(args); break; } if((strcmp(args[0],"fg")==0) && (flag == FALSE)) { fgCmd(args); break; } if(ampCount(multiCmd[i])) { printf(" dash: syntax error near unexpected token '&' \n"); break; } if ( (pid = fork()) < 0) // Forking a Process err_sys("fork error"); else if (pid == 0) { struct stat buf; /* child */ if(flag == TRUE) { if(setpgid(0,0)!=0) perror("setpid() error"); if(tcsetpgrp(0,tcpid)!=0) perror("tcsetpgrp() error"); } if(ior->input != NULL) { if((fd1 = stat(ior->input,&buf))==-1){ printf("dash: %s file does not exist\n",ior->input); break; } if((fd1= access(ior->input,R_OK))==-1){ printf("dash: %s permission denied\n",ior->input); break; } if((fd1 = open(ior->input,O_RDONLY))==-1){ printf("dash: %s inpRedirect opening failed\n",ior->input); break; } else { close(0); dup(fd1); } } if(ior->output != NULL) { /*if((fd1= access(ior->output,W_OK))==-1){ printf("dash: %s permission denied",ior->output); break;}*/ if((fd2=open(ior->output,O_WRONLY|O_TRUNC|O_CREAT,S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH ))==-1){ printf("dash: %s outRedirect opening failed\n",ior->output); break;} else{ close(1); dup(fd2); } } if (setpgid(0,0) != 0) perror("setpgid() error"); if (tcsetpgrp(0, getpid()) != 0) perror("tcsetpgrp() error"); execvp(args[0],args); err_ret("couldn't execute: %s", line); exit(127); } if(flag == TRUE && (*args[0] !='\0')) { jobid = assignJobId(); myObj = createObject(pid,multiCmd[i],jobid,1); node = createNode(myObj); addAtRear(lst,node); printf("[%d] %d %s &\n",((ObjectPtr)(node->obj))->jobId, ((ObjectPtr)(node->obj))->key, ((ObjectPtr)(node->obj))->data); if ( (pid = waitpid(pid, &status, WNOHANG)) < 0) err_sys("waitpid error"); if((tcsetpgrp(0,tcpid))!=0) perror("tcsetgroup error"); } else { if ( (pid = waitpid(pid, &status, 0|WUNTRACED)) < 0) err_sys("waitpid error"); if((tcsetpgrp(0,tcpid))!=0) perror("tcsetgroup error"); if(WIFSTOPPED(status)) { jobid = assignJobId(); myObj = createObject(pid,line,jobid,2); node = createNode(myObj); addAtRear(lst,node); printf("%s\n",(*toString)(node->obj)); } } i++; } freeVar(line,str,args); memset(multiCmd,'\0',sizeof(multiCmd)); i=0; } freeList(lst); exit(0); }
static ptid_t obsd_wait (struct target_ops *ops, ptid_t ptid, struct target_waitstatus *ourstatus, int options) { pid_t pid; int status, save_errno; do { set_sigint_trap (); do { pid = waitpid (ptid_get_pid (ptid), &status, 0); save_errno = errno; } while (pid == -1 && errno == EINTR); clear_sigint_trap (); if (pid == -1) { fprintf_unfiltered (gdb_stderr, _("Child process unexpectedly missing: %s.\n"), safe_strerror (save_errno)); /* Claim it exited with unknown signal. */ ourstatus->kind = TARGET_WAITKIND_SIGNALLED; ourstatus->value.sig = GDB_SIGNAL_UNKNOWN; return inferior_ptid; } /* Ignore terminated detached child processes. */ if (!WIFSTOPPED (status) && pid != ptid_get_pid (inferior_ptid)) pid = -1; } while (pid == -1); ptid = pid_to_ptid (pid); if (WIFSTOPPED (status)) { ptrace_state_t pe; pid_t fpid; if (ptrace (PT_GET_PROCESS_STATE, pid, (caddr_t)&pe, sizeof pe) == -1) perror_with_name (("ptrace")); switch (pe.pe_report_event) { case PTRACE_FORK: ourstatus->kind = TARGET_WAITKIND_FORKED; ourstatus->value.related_pid = pid_to_ptid (pe.pe_other_pid); /* Make sure the other end of the fork is stopped too. */ fpid = waitpid (pe.pe_other_pid, &status, 0); if (fpid == -1) perror_with_name (("waitpid")); if (ptrace (PT_GET_PROCESS_STATE, fpid, (caddr_t)&pe, sizeof pe) == -1) perror_with_name (("ptrace")); gdb_assert (pe.pe_report_event == PTRACE_FORK); gdb_assert (pe.pe_other_pid == pid); if (fpid == ptid_get_pid (inferior_ptid)) { ourstatus->value.related_pid = pid_to_ptid (pe.pe_other_pid); return pid_to_ptid (fpid); } return pid_to_ptid (pid); } ptid = ptid_build (pid, pe.pe_tid, 0); if (!in_thread_list (ptid)) { if (ptid_get_lwp (inferior_ptid) == 0) thread_change_ptid (inferior_ptid, ptid); else add_thread (ptid); } } store_waitstatus (ourstatus, status); return ptid; }
void execute(const string& script) { // Create a temporary directory for the test. Try<string> directory = environment->mkdtemp(); CHECK_SOME(directory) << "Failed to create temporary directory"; if (flags.verbose) { std::cerr << "Using temporary directory '" << directory.get() << "'" << std::endl; } // Determine the path for the script. Result<string> path = os::realpath(getTestScriptPath(script)); if (!path.isSome()) { FAIL() << "Failed to locate script " << script << ": " << (path.isError() ? path.error() : "No such file or directory"); } // Fork a process to change directory and run the test. pid_t pid; if ((pid = fork()) == -1) { FAIL() << "Failed to fork to launch script"; } if (pid > 0) { // In parent process. int status; while (wait(&status) != pid || WIFSTOPPED(status)); CHECK(WIFEXITED(status) || WIFSIGNALED(status)); if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { FAIL() << script << " " << WSTRINGIFY(status); } } else { // In child process. DO NOT USE GLOG! // Start by cd'ing into the temporary directory. Try<Nothing> chdir = os::chdir(directory.get()); if (chdir.isError()) { std::cerr << "Failed to chdir to '" << directory.get() << "': " << chdir.error() << std::endl; abort(); } // Redirect output to /dev/null unless the test is verbose. if (!flags.verbose) { if (freopen("/dev/null", "w", stdout) == NULL || freopen("/dev/null", "w", stderr) == NULL) { std::cerr << "Failed to redirect stdout/stderr to /dev/null:" << os::strerror(errno) << std::endl; abort(); } } // Set up the environment for executing the script. We might be running from // the Mesos source tree or from an installed version of the tests. In the // latter case, all of the variables below are swizzled to point to the // installed locations, except MESOS_SOURCE_DIR. Scripts that make use of // MESOS_SOURCE_DIR are expected to gracefully degrade if the Mesos source // is no longer present. os::setenv("MESOS_BUILD_DIR", flags.build_dir); os::setenv("MESOS_HELPER_DIR", getTestHelperDir()); os::setenv("MESOS_LAUNCHER_DIR", getLauncherDir()); os::setenv("MESOS_SBIN_DIR", getSbinDir()); os::setenv("MESOS_SOURCE_DIR", flags.source_dir); os::setenv("MESOS_WEBUI_DIR", getWebUIDir()); // Enable replicated log based registry. os::setenv("MESOS_REGISTRY", "replicated_log"); // Enable authentication. os::setenv("MESOS_AUTHENTICATE", "true"); // Create test credentials. const string& credentials = DEFAULT_CREDENTIAL.principal() + " " + DEFAULT_CREDENTIAL.secret(); const string& credentialsPath = path::join(directory.get(), "credentials"); CHECK_SOME(os::write(credentialsPath, credentials)) << "Failed to write credentials to '" << credentialsPath << "'"; os::setenv("MESOS_CREDENTIALS", "file://" + credentialsPath); // We set test credentials here for example frameworks to use. os::setenv("DEFAULT_PRINCIPAL", DEFAULT_CREDENTIAL.principal()); os::setenv("DEFAULT_SECRET", DEFAULT_CREDENTIAL.secret()); // TODO(bmahler): Update the example frameworks to use flags and // remove the special DEFAULT_* environment variables above. os::setenv("MESOS_PRINCIPAL", DEFAULT_CREDENTIAL.principal()); os::setenv("MESOS_SECRET", DEFAULT_CREDENTIAL.secret()); // Create test ACLs. ACLs acls; acls.set_permissive(false); mesos::ACL::RunTask* run = acls.add_run_tasks(); run->mutable_principals()->add_values(DEFAULT_CREDENTIAL.principal()); Result<string> user = os::user(); CHECK_SOME(user) << "Failed to get current user name"; run->mutable_users()->add_values(user.get()); mesos::ACL::RegisterFramework* register_ = acls.add_register_frameworks(); register_->mutable_principals()->add_values(DEFAULT_CREDENTIAL.principal()); register_->mutable_roles()->add_values("*"); const string& aclsPath = path::join(directory.get(), "acls"); CHECK_SOME(os::write(aclsPath, stringify(JSON::protobuf(acls)))) << "Failed to write ACLs to '" << aclsPath << "'"; os::setenv("MESOS_ACLS", "file://" + aclsPath); // Now execute the script. execl(path.get().c_str(), path.get().c_str(), (char*) NULL); std::cerr << "Failed to execute '" << script << "': " << os::strerror(errno) << std::endl; abort(); } }