Diff for /libaitio/src/exec.c between versions 1.1.2.3 and 1.1.2.4

version 1.1.2.3, 2013/12/05 13:22:10 version 1.1.2.4, 2013/12/05 14:12:25
Line 1 Line 1
 #include "global.h"  #include "global.h"
   
   
   extern char **environ;
   extern int __isthreaded;
   
   struct pid {
           SLIST_ENTRY(pid) next;
           FILE *fp;
           pid_t pid;
   };
   static SLIST_HEAD(, pid) pidlist = SLIST_HEAD_INITIALIZER(pidlist);
   static pthread_mutex_t pidlist_mutex = PTHREAD_MUTEX_INITIALIZER;
   
   #define THREAD_LOCK()   if (__isthreaded) pthread_mutex_lock(&pidlist_mutex)
   #define THREAD_UNLOCK() if (__isthreaded) pthread_mutex_unlock(&pidlist_mutex)
   
   
 /*  /*
  * io_progInit() - Init program pool   * io_progInit() - Init program pool
  *   *
Line 87  io_progClose(prog_t * __restrict prg, u_int closeNum) Line 102  io_progClose(prog_t * __restrict prg, u_int closeNum)
         for (i = array_Size(prg->prog_fds) - 1;           for (i = array_Size(prg->prog_fds) - 1; 
                         (closeNum ? ret < closeNum : 42) && i > -1; i--)                          (closeNum ? ret < closeNum : 42) && i > -1; i--)
                 if (array_Get(prg->prog_fds, i)) {                  if (array_Get(prg->prog_fds, i)) {
                        pclose(array(prg->prog_fds, i, FILE*));                        io_pclose(array(prg->prog_fds, i, FILE*));
                         array_Del(prg->prog_fds, i, 0);                          array_Del(prg->prog_fds, i, 0);
                         prg->prog_cnum--;                          prg->prog_cnum--;
                         ret++;                          ret++;
Line 108  int Line 123  int
 io_progOpen(prog_t * __restrict prg, u_int execNum)  io_progOpen(prog_t * __restrict prg, u_int execNum)
 {  {
         FILE *f;          FILE *f;
        int ret = 0;        int stat, ret = 0;
         register int i;          register int i;
           pid_t pid;
   
         if (!prg)          if (!prg)
                 return 0;                  return 0;
Line 121  io_progOpen(prog_t * __restrict prg, u_int execNum) Line 137  io_progOpen(prog_t * __restrict prg, u_int execNum)
         pthread_mutex_lock(&prg->prog_mtx);          pthread_mutex_lock(&prg->prog_mtx);
         for (i = 0; (execNum ? ret < execNum : 42) && i < array_Size(prg->prog_fds); i++)          for (i = 0; (execNum ? ret < execNum : 42) && i < array_Size(prg->prog_fds); i++)
                 if (!array_Get(prg->prog_fds, i)) {                  if (!array_Get(prg->prog_fds, i)) {
                        f = popen(prg->prog_name, "r+");                        f = io_popen(prg->prog_name, "r+", &pid);
                         if (!f) {                          if (!f) {
                                 LOGERR;                                  LOGERR;
                                 ret *= -1;                                  ret *= -1;
                                 break;                                  break;
                           } else if (waitpid(pid, &stat, WNOHANG) > 0) {
                                   io_SetErr(ECHILD, "Program exit with status %d", 
                                                   WIFEXITED(stat) ? WEXITSTATUS(stat) : -1);
                                   ret *= -1;
                                   break;
                         } else                          } else
                                 array_Set(prg->prog_fds, i, f);                                  array_Set(prg->prog_fds, i, f);
                         prg->prog_cnum++;                          prg->prog_cnum++;
Line 161  io_progVacuum(prog_t * __restrict prg, u_int toNum) Line 182  io_progVacuum(prog_t * __restrict prg, u_int toNum)
         pthread_mutex_lock(&prg->prog_mtx);          pthread_mutex_lock(&prg->prog_mtx);
         for (i = array_Size(prg->prog_fds) - 1; prg->prog_cnum > toNum && i > -1; i--)          for (i = array_Size(prg->prog_fds) - 1; prg->prog_cnum > toNum && i > -1; i--)
                 if (array_Get(prg->prog_fds, i)) {                  if (array_Get(prg->prog_fds, i)) {
                        pclose(array(prg->prog_fds, i, FILE*));                        io_pclose(array(prg->prog_fds, i, FILE*));
                         array_Del(prg->prog_fds, i, 0);                          array_Del(prg->prog_fds, i, 0);
                         prg->prog_cnum--;                          prg->prog_cnum--;
                         ret++;                          ret++;
Line 169  io_progVacuum(prog_t * __restrict prg, u_int toNum) Line 190  io_progVacuum(prog_t * __restrict prg, u_int toNum)
         pthread_mutex_unlock(&prg->prog_mtx);          pthread_mutex_unlock(&prg->prog_mtx);
   
         return ret;          return ret;
   }
   
   
   /*
    * io_popen() - ELWIX replacement of standard popen
    *
    * @command = command
    * @type = type
    * @ppid = return pid of child program
    * return: NULL error or !=NULL open program
    */
   FILE *
   io_popen(const char *command, const char *type, pid_t *ppid)
   {
           struct pid *cur;
           FILE *iop;
           int pdes[2], pid, twoway, cloexec;
           char *argv[4];
           struct pid *p;
   
           cloexec = strchr(type, 'e') != NULL;
           /*
            * Lite2 introduced two-way popen() pipes using _socketpair().
            * FreeBSD's pipe() is bidirectional, so we use that.
            */
           if (strchr(type, '+')) {
                   twoway = 1;
                   type = "r+";
           } else  {
                   twoway = 0;
                   if ((*type != 'r' && *type != 'w') ||
                       (type[1] && (type[1] != 'e' || type[2])))
                           return (NULL);
           }
           if ((cloexec ? pipe2(pdes, O_CLOEXEC) : pipe(pdes)) < 0)
                   return (NULL);
   
           if ((cur = e_malloc(sizeof(struct pid))) == NULL) {
                   close(pdes[0]);
                   close(pdes[1]);
                   return (NULL);
           }
   
           argv[0] = "sh";
           argv[1] = "-c";
           argv[2] = (char *)command;
           argv[3] = NULL;
   
           THREAD_LOCK();
           switch (pid = vfork()) {
           case -1:                        /* Error. */
                   THREAD_UNLOCK();
                   close(pdes[0]);
                   close(pdes[1]);
                   e_free(cur);
                   return (NULL);
                   /* NOTREACHED */
           case 0:                         /* Child. */
                   if (*type == 'r') {
                           /*
                            * The _dup2() to STDIN_FILENO is repeated to avoid
                            * writing to pdes[1], which might corrupt the
                            * parent's copy.  This isn't good enough in
                            * general, since the _exit() is no return, so
                            * the compiler is free to corrupt all the local
                            * variables.
                            */
                           if (!cloexec)
                                   close(pdes[0]);
                           if (pdes[1] != STDOUT_FILENO) {
                                   dup2(pdes[1], STDOUT_FILENO);
                                   if (!cloexec)
                                           close(pdes[1]);
                                   if (twoway)
                                           dup2(STDOUT_FILENO, STDIN_FILENO);
                           } else if (twoway && (pdes[1] != STDIN_FILENO)) {
                                   dup2(pdes[1], STDIN_FILENO);
                                   if (cloexec)
                                           fcntl(pdes[1], F_SETFD, 0);
                           } else if (cloexec)
                                   fcntl(pdes[1], F_SETFD, 0);
                   } else {
                           if (pdes[0] != STDIN_FILENO) {
                                   dup2(pdes[0], STDIN_FILENO);
                                   if (!cloexec)
                                           close(pdes[0]);
                           } else if (cloexec)
                                   fcntl(pdes[0], F_SETFD, 0);
                           if (!cloexec)
                                   close(pdes[1]);
                   }
                   SLIST_FOREACH(p, &pidlist, next)
                           close(fileno(p->fp));
                   execve(_PATH_BSHELL, argv, environ);
                   _exit(127);
                   /* NOTREACHED */
           default:
                   if (ppid)
                           *ppid = pid;
           }
           THREAD_UNLOCK();
   
           /* Parent; assume fdopen can't fail. */
           if (*type == 'r') {
                   iop = fdopen(pdes[0], type);
                   close(pdes[1]);
           } else {
                   iop = fdopen(pdes[1], type);
                   close(pdes[0]);
           }
   
           /* Link into list of file descriptors. */
           cur->fp = iop;
           cur->pid = pid;
           THREAD_LOCK();
           SLIST_INSERT_HEAD(&pidlist, cur, next);
           THREAD_UNLOCK();
   
           return (iop);
   }
   
   /*
    * io_pclose() - ELWIX replacement of standard pclose
    *
    * @iop = popen handle
    * return: -1 error or !=-1 pid status
    */
   int
   io_pclose(FILE *iop)
   {
           struct pid *cur, *last = NULL;
           int pstat;
           pid_t pid;
   
           /*
            * Find the appropriate file pointer and remove it from the list.
            */
           THREAD_LOCK();
           SLIST_FOREACH(cur, &pidlist, next) {
                   if (cur->fp == iop)
                           break;
                   last = cur;
           }
           if (cur == NULL) {
                   THREAD_UNLOCK();
                   return (-1);
           }
           if (last == NULL)
                   SLIST_REMOVE_HEAD(&pidlist, next);
           else
                   SLIST_REMOVE_AFTER(last, next);
           THREAD_UNLOCK();
   
           fclose(iop);
   
           do {
                   pid = wait4(cur->pid, &pstat, 0, (struct rusage *)0);
           } while (pid == -1 && errno == EINTR);
   
           e_free(cur);
   
           return (pid == -1 ? -1 : pstat);
 }  }

Removed from v.1.1.2.3  
changed lines
  Added in v.1.1.2.4


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>