IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Jul 4, 2005, 5:35:47 PM (21 years ago)
Author:
eugene
Message:

substantial dev work on scheduler/pcontrol/pclient

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Ohana/src/opihi/pantasks/LocalJob.c

    r3392 r4450  
     1# include "scheduler.h"
    12
    2 /* local jobs are forked in the background */
     3/* this could be written a just a one-way pipe */
     4int SubmitLocalJob (Job *job) {
    35
    4 SubmitLocalJob (Job *job) {
     6  int status, pid;
     7  int stdout_fd[2], stderr_fd[2];
    58
    6   /*
    7      construct the command line
    8      fork the command, get back the PID
    9      increment local job counter
    10   */
     9  bzero (stdout_fd, 2*sizeof(int));
     10  bzero (stderr_fd, 2*sizeof(int));
    1111
     12  if (pipe (stdout_fd) < 0) goto pipe_error;
     13  if (pipe (stderr_fd) < 0) goto pipe_error;
     14
     15  pid = fork ();
     16  if (!pid) { /* must be child process */
     17    fprintf (stderr, "starting controller connection\n");
     18
     19    /* close the other ends of the pipes */
     20    close (stdout_fd[0]);
     21    close (stderr_fd[0]);
     22
     23    /* tie our ends of the pipes to stdin, stdout, stderr */
     24    dup2 (stdout_fd[1], STDOUT_FILENO);
     25    dup2 (stderr_fd[1], STDERR_FILENO);
     26
     27    /* set all three unblocking */
     28    setvbuf (stdout, (char *) NULL, _IONBF, BUFSIZ);
     29    setvbuf (stderr, (char *) NULL, _IONBF, BUFSIZ);
     30
     31    status = execvp (job[0].argv[0], job[0].argv);
     32    exit (1);
     33  }
     34
     35  /* close the other ends of the pipes */
     36  close (stdout_fd[1]); stdout_fd[1] = 0;
     37  close (stderr_fd[1]); stderr_fd[1] = 0;
     38
     39  /* make the pipes non-blocking */
     40  fcntl (stdout_fd[0], F_SETFL, O_NONBLOCK);
     41  fcntl (stderr_fd[0], F_SETFL, O_NONBLOCK);
     42
     43  job[0].stdout_fd = stdout_fd[0];
     44  job[0].stderr_fd = stderr_fd[0];
     45  job[0].pid = pid;
     46
     47  return (TRUE);
     48
     49pipe_error:
     50  perror ("pipe error:");
     51  if (stdout_fd[0] != 0) close (stdout_fd[0]);
     52  if (stdout_fd[1] != 0) close (stdout_fd[1]);
     53  if (stderr_fd[0] != 0) close (stderr_fd[0]);
     54  if (stderr_fd[1] != 0) close (stderr_fd[1]);
     55  return (FALSE);
    1256}
    1357
    14 CheckLocalJob (Job *job) {
     58/* update current state, drain stdout/stderr buffers */
     59int CheckLocalJob (Job *job) {
    1560
    16   /*
    17      
     61  int Nread;
     62
     63  // XXX do something useful with exit status?
     64  CheckLocalJobStatus (job);
     65
     66  /* read stdout buffer */
     67  Nread = ReadtoIOBuffer (&job[0].stdout, job[0].stdout_fd);
     68  switch (Nread) {
     69    case -2:  /* error in read (programming error?  system level error?) */
     70      fprintf (stderr, "serious IO error\n");
     71      exit (2);
     72    case -1:  /* no data in pipe */
     73      break;
     74    case 0:   /* pipe is closed */
     75      /** change child state? **/
     76      break;
     77    default:  /* data in pipe */
     78      break;
     79  }
     80 
     81  /* read stderr buffer */
     82  Nread = ReadtoIOBuffer (&job[0].stderr, job[0].stderr_fd);
     83  switch (Nread) {
     84    case -2:  /* error in read (programming error?  system level error?) */
     85      fprintf (stderr, "serious IO error\n");
     86      exit (2);
     87    case -1:  /* no data in pipe */
     88      break;
     89    case 0:   /* pipe is closed */
     90      /** change child state? **/
     91      break;
     92    default:  /* data in pipe */
     93      break;
     94  }
     95  return (TRUE);
     96}
     97
     98int CheckLocalJobStatus (Job *job) {
     99
     100  int result, waitstatus;
     101
     102  /* check local job status */
     103  result = waitpid (job[0].pid, &waitstatus, WNOHANG);
     104  switch (result) {
     105    case -1:  /* error with waitpid */
     106      switch (errno) {
     107        case ECHILD:
     108          fprintf (stderr, "unknown PID, not a child proc\n");
     109          fprintf (stderr, "did process already exit?  programming error?\n");
     110          job[0].state = JOB_NONE;
     111          job[0].exit_status = 0;
     112          return (FALSE);
     113        case EINVAL:
     114          fprintf (stderr, "error EINVAL (waitpid): programming error\n");
     115          exit (1);
     116        case EINTR:
     117          fprintf (stderr, "error EINTR (waitpid): programming error\n");
     118          exit (1);
     119        default:
     120          fprintf (stderr, "unknown error for waitpid (%d): programming error\n", errno);
     121          exit (1);
     122      }
     123      break;
     124     
     125    case 0:  /* process not exited */
     126      job[0].state = JOB_BUSY;
     127      job[0].exit_status = 0;
     128      return (TRUE);
     129
     130    default:
     131      if (result != job[0].pid) {
     132        fprintf (stderr, "waitpid error: mis-matched PID (%d vs %d).  programming error\n", result, job[0].pid);
     133        exit (1);
     134      }
     135     
     136      if (WIFEXITED(waitstatus)) {
     137        job[0].state = JOB_EXIT;
     138        job[0].exit_status = WEXITSTATUS(waitstatus);
     139      }
     140      if (WIFSIGNALED(waitstatus)) {
     141        job[0].state = JOB_CRASH;
     142        job[0].exit_status = WTERMSIG(waitstatus);
     143      }
     144      if (WIFSTOPPED(waitstatus)) {
     145        fprintf (stderr, "waitpid returns 'stopped': programming error\n");
     146        exit (1);
     147      }
     148  }
     149  return;
     150}
Note: See TracChangeset for help on using the changeset viewer.