Diff for /libaitio/src/exec.c between versions 1.1.2.5 and 1.1.2.6

version 1.1.2.5, 2013/12/05 14:16:33 version 1.1.2.6, 2013/12/05 15:18:22
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 52  io_progInit(const char *progName, u_int initNum, u_int Line 37  io_progInit(const char *progName, u_int initNum, u_int
   
         pthread_mutex_init(&prg->prog_mtx, NULL);          pthread_mutex_init(&prg->prog_mtx, NULL);
   
        if (io_progOpen(prg, prg->prog_inin) < 0)        if (io_progOpen(prg, prg->prog_inin) < 0) {
                 io_progDestroy(&prg);                  io_progDestroy(&prg);
                   prg = NULL;
           }
         return prg;          return prg;
 }  }
   
Line 102  io_progClose(prog_t * __restrict prg, u_int closeNum) Line 89  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)) {
                        io_pclose(array(prg->prog_fds, i, FILE*));                        e_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 137  io_progOpen(prog_t * __restrict prg, u_int execNum) Line 124  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 = io_popen(prg->prog_name, "r+", &pid);                        f = e_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) {                        } else if (waitpid(pid, &stat, WNOHANG)) {
                                io_SetErr(ECHILD, "Program exit with status %d",                                 io_SetErr(ECHILD, "Program with pid=%d exit with status %d", 
                                                WIFEXITED(stat) ? WEXITSTATUS(stat) : -1);                                                pid, WIFEXITED(stat) ? WEXITSTATUS(stat) : -1);
                                 ret = -1;                                  ret = -1;
                                 break;                                  break;
                         } else                          } else
Line 182  io_progVacuum(prog_t * __restrict prg, u_int toNum) Line 169  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)) {
                        io_pclose(array(prg->prog_fds, i, FILE*));                        e_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 190  io_progVacuum(prog_t * __restrict prg, u_int toNum) Line 177  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.5  
changed lines
  Added in v.1.1.2.6


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