Annotation of libaitio/src/exec.c, revision 1.1.2.14

1.1.2.1   misho       1: #include "global.h"
                      2: 
                      3: 
                      4: /*
                      5:  * io_progInit() - Init program pool
                      6:  *
                      7:  * @progName = program name for execution
                      8:  * @initNum = initial started programs
                      9:  * @maxNum = maximum started programs
                     10:  * return: NULL error or !=NULL allocated pool (must destroied with io_progDestroy())
                     11:  */
                     12: prog_t *
                     13: io_progInit(const char *progName, u_int initNum, u_int maxNum)
                     14: {
                     15:        prog_t *prg = NULL;
                     16: 
                     17:        if (initNum > maxNum)
                     18:                return NULL;
                     19: 
                     20:        prg = e_malloc(sizeof(prog_t));
                     21:        if (!prg) {
                     22:                io_SetErr(elwix_GetErrno(), "%s", elwix_GetError());
                     23:                return NULL;
                     24:        } else
                     25:                memset(prg, 0, sizeof(prog_t));
                     26: 
                     27:        prg->prog_inin = initNum;
                     28:        prg->prog_maxn = maxNum;
                     29:        strlcpy(prg->prog_name, progName, sizeof prg->prog_name);
                     30: 
1.1.2.9   misho      31:        prg->prog_used = e_malloc(E_ALIGN(prg->prog_maxn, sizeof *prg->prog_used) / 
                     32:                        sizeof *prg->prog_used);
                     33:        if (!prg->prog_used) {
                     34:                io_SetErr(elwix_GetErrno(), "%s", elwix_GetError());
                     35:                e_free(prg);
                     36:                return NULL;
                     37:        }
                     38: 
1.1.2.1   misho      39:        prg->prog_fds = array_Init(prg->prog_maxn);
                     40:        if (!prg->prog_fds) {
                     41:                io_SetErr(elwix_GetErrno(), "%s", elwix_GetError());
1.1.2.9   misho      42:                e_free(prg->prog_used);
1.1.2.1   misho      43:                e_free(prg);
                     44:                return NULL;
                     45:        }
                     46: 
                     47:        pthread_mutex_init(&prg->prog_mtx, NULL);
1.1.2.12  misho      48:        signal(SIGPIPE, SIG_IGN);
1.1.2.2   misho      49: 
1.1.2.6   misho      50:        if (io_progOpen(prg, prg->prog_inin) < 0) {
1.1.2.2   misho      51:                io_progDestroy(&prg);
1.1.2.6   misho      52:                prg = NULL;
                     53:        }
1.1.2.1   misho      54:        return prg;
                     55: }
                     56: 
                     57: /*
                     58:  * io_progDestroy() - Destroy entire program pool
                     59:  *
                     60:  * @pprg = program pool
                     61:  * return: none
                     62:  */
                     63: void
                     64: io_progDestroy(prog_t ** __restrict pprg)
                     65: {
                     66:        if (!pprg || !*pprg)
                     67:                return;
                     68: 
                     69:        io_progClose(*pprg, 0);
                     70: 
1.1.2.9   misho      71:        e_free((*pprg)->prog_used);
1.1.2.1   misho      72:        array_Destroy(&(*pprg)->prog_fds);
                     73:        pthread_mutex_destroy(&(*pprg)->prog_mtx);
1.1.2.13  misho      74:        signal(SIGPIPE, SIG_DFL);
1.1.2.1   misho      75: 
                     76:        e_free(*pprg);
                     77:        *pprg = NULL;
                     78: }
                     79: 
                     80: /*
                     81:  * io_progClose() - Close all programs in pool
                     82:  *
                     83:  * @prg = program pool
                     84:  * @closeNum = close program(s) (0 all)
                     85:  * return: 0 error, >0 closed programs
                     86:  */
                     87: int
                     88: io_progClose(prog_t * __restrict prg, u_int closeNum)
                     89: {
                     90:        register int i;
                     91:        int ret = 0;
1.1.2.14! misho      92:        struct tagPIOPID *p;
1.1.2.1   misho      93: 
                     94:        if (!prg)
                     95:                return 0;
                     96:        if (closeNum > prg->prog_maxn) {
                     97:                io_SetErr(EINVAL, "Requested number for close program is over pool's limit");
                     98:                return 0;
                     99:        }
                    100: 
                    101:        pthread_mutex_lock(&prg->prog_mtx);
                    102:        for (i = array_Size(prg->prog_fds) - 1; 
                    103:                        (closeNum ? ret < closeNum : 42) && i > -1; i--)
1.1.2.14! misho     104:                if (array_Get(prg->prog_fds, i) && 
        !           105: #ifdef POPEN_STREAM
        !           106:                                (p = pio_pgetpid(array(prg->prog_fds, i, FILE*)))) {
        !           107: #else
        !           108:                                (p = pio_pgetpid((int) array(prg->prog_fds, i, intptr_t)))) {
        !           109: #endif
        !           110:                        kill(p->pid, SIGTERM);
        !           111:                        usleep(1000);
        !           112:                        if (waitpid(p->pid, &p->stat, WNOHANG) > 0)
        !           113:                                kill(p->pid, SIGKILL);
1.1.2.11  misho     114: #ifdef POPEN_STREAM
1.1.2.6   misho     115:                        e_pclose(array(prg->prog_fds, i, FILE*));
1.1.2.11  misho     116: #else
                    117:                        e_pclose((int) array(prg->prog_fds, i, intptr_t));
                    118: #endif
1.1.2.1   misho     119:                        array_Del(prg->prog_fds, i, 0);
1.1.2.9   misho     120:                        clrbit(prg->prog_used, i);
1.1.2.1   misho     121:                        prg->prog_cnum--;
                    122:                        ret++;
                    123:                }
                    124:        pthread_mutex_unlock(&prg->prog_mtx);
                    125: 
                    126:        return ret;
                    127: }
                    128: 
                    129: /*
1.1.2.14! misho     130:  * io_progCloseAt() - Close program at pool of certain position
        !           131:  *
        !           132:  * @prg = program pool
        !           133:  * @idx = index at pool
        !           134:  * return: 0 error or !=0 closed program
        !           135:  */
        !           136: int
        !           137: io_progCloseAt(prog_t * __restrict prg, u_int idx)
        !           138: {
        !           139:        int ret = 0;
        !           140:        struct tagPIOPID *p;
        !           141: 
        !           142:        if (!prg)
        !           143:                return 0;
        !           144:        if (idx > prg->prog_maxn) {
        !           145:                io_SetErr(EINVAL, "Requested number for close program is over pool's limit");
        !           146:                return 0;
        !           147:        }
        !           148: 
        !           149:        pthread_mutex_lock(&prg->prog_mtx);
        !           150:        if (array_Get(prg->prog_fds, idx) && 
        !           151: #ifdef POPEN_STREAM
        !           152:                        (p = pio_pgetpid(array(prg->prog_fds, idx, FILE*)))) {
        !           153: #else
        !           154:                        (p = pio_pgetpid((int) array(prg->prog_fds, idx, intptr_t)))) {
        !           155: #endif
        !           156:                kill(p->pid, SIGTERM);
        !           157:                usleep(1000);
        !           158:                if (waitpid(p->pid, &p->stat, WNOHANG) > 0)
        !           159:                        kill(p->pid, SIGKILL);
        !           160: #ifdef POPEN_STREAM
        !           161:                e_pclose(array(prg->prog_fds, idx, FILE*));
        !           162: #else
        !           163:                e_pclose((int) array(prg->prog_fds, idx, intptr_t));
        !           164: #endif
        !           165:                array_Del(prg->prog_fds, idx, 0);
        !           166:                clrbit(prg->prog_used, idx);
        !           167:                prg->prog_cnum--;
        !           168:                ret++;
        !           169:        }
        !           170:        pthread_mutex_unlock(&prg->prog_mtx);
        !           171: 
        !           172:        return ret;
        !           173: }
        !           174: 
        !           175: /*
1.1.2.1   misho     176:  * io_progOpen() - Execute number of program(s)
                    177:  *
                    178:  * @prg = program pool
                    179:  * @execNum = execute program(s) (0 max)
                    180:  * return: 0 error, >0 executed programs and abs(<0) executed programs with logged error
                    181:  */
                    182: int
                    183: io_progOpen(prog_t * __restrict prg, u_int execNum)
                    184: {
1.1.2.11  misho     185: #ifdef POPEN_STREAM
1.1.2.1   misho     186:        FILE *f;
1.1.2.11  misho     187: #else
                    188:        int f;
                    189: #endif
1.1.2.4   misho     190:        int stat, ret = 0;
1.1.2.1   misho     191:        register int i;
1.1.2.4   misho     192:        pid_t pid;
1.1.2.1   misho     193: 
                    194:        if (!prg)
                    195:                return 0;
1.1.2.8   misho     196:        if (prg->prog_cnum + execNum > prg->prog_maxn) {
1.1.2.1   misho     197:                io_SetErr(EINVAL, "Requested number for program execution is over pool's limit");
                    198:                return 0;
                    199:        }
                    200: 
                    201:        pthread_mutex_lock(&prg->prog_mtx);
                    202:        for (i = 0; (execNum ? ret < execNum : 42) && i < array_Size(prg->prog_fds); i++)
                    203:                if (!array_Get(prg->prog_fds, i)) {
1.1.2.6   misho     204:                        f = e_popen(prg->prog_name, "r+", &pid);
1.1.2.11  misho     205: #ifdef POPEN_STREAM
1.1.2.1   misho     206:                        if (!f) {
1.1.2.11  misho     207: #else
                    208:                        if (f == -1) {
                    209: #endif
1.1.2.1   misho     210:                                LOGERR;
1.1.2.5   misho     211:                                ret = -1;
1.1.2.1   misho     212:                                break;
1.1.2.6   misho     213:                        } else if (waitpid(pid, &stat, WNOHANG)) {
                    214:                                io_SetErr(ECHILD, "Program with pid=%d exit with status %d", 
                    215:                                                pid, WIFEXITED(stat) ? WEXITSTATUS(stat) : -1);
1.1.2.5   misho     216:                                ret = -1;
1.1.2.4   misho     217:                                break;
1.1.2.1   misho     218:                        } else
                    219:                                array_Set(prg->prog_fds, i, f);
                    220:                        prg->prog_cnum++;
                    221:                        ret++;
                    222:                }
                    223:        pthread_mutex_unlock(&prg->prog_mtx);
                    224: 
                    225:        return ret;
                    226: }
                    227: 
                    228: /*
1.1.2.8   misho     229:  * io_progGrow() - Execute to number of programs in pool
                    230:  *
                    231:  * @prg = program pool
                    232:  * @toNum = execute to number of programs (0 max)
                    233:  * return: 0 error, >0 executed programs and abs(<0) executed programs with logged error
                    234:  */
                    235: int
                    236: io_progGrow(prog_t * __restrict prg, u_int toNum)
                    237: {
                    238:        if (!prg)
                    239:                return 0;
                    240:        if (toNum > prg->prog_maxn) {
                    241:                io_SetErr(EINVAL, "Requested number for program execution is over pool's limit");
                    242:                return 0;
                    243:        }
                    244:        if (!toNum)
                    245:                toNum = prg->prog_maxn;
                    246: 
                    247:        return io_progOpen(prg, toNum - prg->prog_cnum);
                    248: }
                    249: 
                    250: /*
1.1.2.1   misho     251:  * io_progVacuum() - Vacuum pool to running number of programs
                    252:  *
                    253:  * @prg = program pool
                    254:  * @toNum = vacuum to number of programs (0 to init number)
                    255:  * return: 0 error or >0 closed programs
                    256:  */
                    257: int
                    258: io_progVacuum(prog_t * __restrict prg, u_int toNum)
                    259: {
                    260:        register int i;
                    261:        int ret = 0;
1.1.2.14! misho     262:        struct tagPIOPID *p;
1.1.2.1   misho     263: 
                    264:        if (!prg)
                    265:                return 0;
                    266:        if (toNum > prg->prog_maxn) {
                    267:                io_SetErr(EINVAL, "Requested number for close program is over pool's limit");
                    268:                return 0;
                    269:        }
                    270:        if (!toNum)
                    271:                toNum = prg->prog_inin;
                    272: 
                    273:        pthread_mutex_lock(&prg->prog_mtx);
                    274:        for (i = array_Size(prg->prog_fds) - 1; prg->prog_cnum > toNum && i > -1; i--)
1.1.2.14! misho     275:                if (array_Get(prg->prog_fds, i) && isclr(prg->prog_used, i) && 
1.1.2.11  misho     276: #ifdef POPEN_STREAM
1.1.2.14! misho     277:                                (p = pio_pgetpid(array(prg->prog_fds, i, FILE*)))) {
        !           278:                        kill(p->pid, SIGTERM);
        !           279:                        usleep(1000);
        !           280:                        if (waitpid(p->pid, &p->stat, WNOHANG) > 0)
        !           281:                                kill(p->pid, SIGKILL);
1.1.2.6   misho     282:                        e_pclose(array(prg->prog_fds, i, FILE*));
1.1.2.11  misho     283: #else
1.1.2.14! misho     284:                                (p = pio_pgetpid((int) array(prg->prog_fds, i, intptr_t)))) {
        !           285:                        kill(p->pid, SIGTERM);
        !           286:                        usleep(1000);
        !           287:                        if (waitpid(p->pid, &p->stat, WNOHANG) > 0)
        !           288:                                kill(p->pid, SIGKILL);
1.1.2.11  misho     289:                        e_pclose((int) array(prg->prog_fds, i, intptr_t));
                    290: #endif
1.1.2.1   misho     291:                        array_Del(prg->prog_fds, i, 0);
                    292:                        prg->prog_cnum--;
                    293:                        ret++;
                    294:                }
                    295:        pthread_mutex_unlock(&prg->prog_mtx);
                    296: 
                    297:        return ret;
                    298: }
1.1.2.7   misho     299: 
                    300: /*
                    301:  * io_progCheck() - Check exit status of program pool
                    302:  *
                    303:  * @prg = program pool
                    304:  * return: -1 error or >-1 exited programs
                    305:  */
                    306: int
                    307: io_progCheck(prog_t * __restrict prg)
                    308: {
                    309:        int ret = 0;
                    310:        struct tagPIOPID *p;
                    311:        register int i;
                    312: 
                    313:        if (!prg)
                    314:                return -1;
                    315: 
1.1.2.9   misho     316:        pthread_mutex_lock(&prg->prog_mtx);
1.1.2.7   misho     317:        for (i = 0; i < array_Size(prg->prog_fds); i++)
                    318:                if (array_Get(prg->prog_fds, i) && 
1.1.2.11  misho     319: #ifdef POPEN_STREAM
1.1.2.7   misho     320:                                (p = pio_pgetpid(array(prg->prog_fds, i, FILE*))))
1.1.2.11  misho     321: #else
                    322:                                (p = pio_pgetpid((int) array(prg->prog_fds, i, intptr_t))))
                    323: #endif
1.1.2.9   misho     324:                        if (waitpid(p->pid, &p->stat, WNOHANG) > 0) {
                    325:                                clrbit(prg->prog_used, i);
1.1.2.7   misho     326:                                ret++;
1.1.2.9   misho     327:                        }
                    328:        pthread_mutex_unlock(&prg->prog_mtx);
1.1.2.7   misho     329: 
                    330:        return ret;
                    331: }
1.1.2.9   misho     332: 
                    333: /*
                    334:  * io_progAttach() - Attach to open program
                    335:  *
                    336:  * @prg = program pool
                    337:  * return: NULL error or !=NULL attached program handle
                    338:  */
1.1.2.11  misho     339: #ifdef POPEN_STREAM
1.1.2.9   misho     340: FILE *
1.1.2.11  misho     341: #else
                    342: int
                    343: #endif
1.1.2.9   misho     344: io_progAttach(prog_t * __restrict prg)
                    345: {
1.1.2.11  misho     346: #ifdef POPEN_STREAM
1.1.2.9   misho     347:        FILE *f = NULL;
1.1.2.11  misho     348: #else
                    349:        int f = -1;
                    350: #endif
1.1.2.9   misho     351:        register int i;
                    352: 
                    353:        if (!prg)
1.1.2.11  misho     354: #ifdef POPEN_STREAM
1.1.2.9   misho     355:                return NULL;
1.1.2.11  misho     356: #else
                    357:                return -1;
                    358: #endif
1.1.2.9   misho     359: 
                    360:        pthread_mutex_lock(&prg->prog_mtx);
                    361:        for (i = 0; i < array_Size(prg->prog_fds); i++)
                    362:                if (array_Get(prg->prog_fds, i) && isclr(prg->prog_used, i)) {
                    363:                        setbit(prg->prog_used, i);
1.1.2.11  misho     364: #ifdef POPEN_STREAM
1.1.2.9   misho     365:                        f = array(prg->prog_fds, i, FILE*);
1.1.2.11  misho     366: #else
                    367:                        f = array(prg->prog_fds, i, intptr_t);
                    368: #endif
1.1.2.9   misho     369:                        break;
                    370:                }
                    371:        pthread_mutex_unlock(&prg->prog_mtx);
                    372: 
                    373:        return f;
                    374: }
                    375: 
                    376: /*
                    377:  * io_progDetach() - Detch from open program
                    378:  *
                    379:  * @prg= program pool
                    380:  * @pfd = attached program handle
                    381:  * return: none
                    382:  */
                    383: void
1.1.2.11  misho     384: #ifdef POPEN_STREAM
1.1.2.9   misho     385: io_progDetach(prog_t * __restrict prg, FILE *pfd)
1.1.2.11  misho     386: #else
                    387: io_progDetach(prog_t * __restrict prg, int pfd)
                    388: #endif
1.1.2.9   misho     389: {
                    390:        register int i;
                    391: 
                    392:        if (!prg || !pfd)
                    393:                return;
                    394: 
                    395:        pthread_mutex_lock(&prg->prog_mtx);
                    396:        for (i = 0; i < array_Size(prg->prog_fds); i++)
1.1.2.11  misho     397: #ifdef POPEN_STREAM
1.1.2.9   misho     398:                if (array(prg->prog_fds, i, FILE*) == pfd) {
1.1.2.11  misho     399: #else
                    400:                if (array(prg->prog_fds, i, intptr_t) == pfd) {
                    401: #endif
1.1.2.9   misho     402:                        clrbit(prg->prog_used, i);
                    403:                        break;
                    404:                }
                    405:        pthread_mutex_unlock(&prg->prog_mtx);
                    406: }

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