File:  [ELWIX - Embedded LightWeight unIX -] / libaitio / src / exec.c
Revision 1.1.2.12: download - view: text, annotated - select for diffs - revision graph
Fri Dec 6 01:30:22 2013 UTC (10 years, 6 months ago) by misho
Branches: io6_7
ignore signal

    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: 
   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: 
   39: 	prg->prog_fds = array_Init(prg->prog_maxn);
   40: 	if (!prg->prog_fds) {
   41: 		io_SetErr(elwix_GetErrno(), "%s", elwix_GetError());
   42: 		e_free(prg->prog_used);
   43: 		e_free(prg);
   44: 		return NULL;
   45: 	}
   46: 
   47: 	pthread_mutex_init(&prg->prog_mtx, NULL);
   48: 	signal(SIGPIPE, SIG_IGN);
   49: 
   50: 	if (io_progOpen(prg, prg->prog_inin) < 0) {
   51: 		io_progDestroy(&prg);
   52: 		prg = NULL;
   53: 	}
   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: 
   71: 	e_free((*pprg)->prog_used);
   72: 	array_Destroy(&(*pprg)->prog_fds);
   73: 	pthread_mutex_destroy(&(*pprg)->prog_mtx);
   74: 
   75: 	e_free(*pprg);
   76: 	*pprg = NULL;
   77: }
   78: 
   79: /*
   80:  * io_progClose() - Close all programs in pool
   81:  *
   82:  * @prg = program pool
   83:  * @closeNum = close program(s) (0 all)
   84:  * return: 0 error, >0 closed programs
   85:  */
   86: int
   87: io_progClose(prog_t * __restrict prg, u_int closeNum)
   88: {
   89: 	register int i;
   90: 	int ret = 0;
   91: 
   92: 	if (!prg)
   93: 		return 0;
   94: 	if (closeNum > prg->prog_maxn) {
   95: 		io_SetErr(EINVAL, "Requested number for close program is over pool's limit");
   96: 		return 0;
   97: 	}
   98: 
   99: 	pthread_mutex_lock(&prg->prog_mtx);
  100: 	for (i = array_Size(prg->prog_fds) - 1; 
  101: 			(closeNum ? ret < closeNum : 42) && i > -1; i--)
  102: 		if (array_Get(prg->prog_fds, i)) {
  103: #ifdef POPEN_STREAM
  104: 			e_pclose(array(prg->prog_fds, i, FILE*));
  105: #else
  106: 			e_pclose((int) array(prg->prog_fds, i, intptr_t));
  107: #endif
  108: 			array_Del(prg->prog_fds, i, 0);
  109: 			clrbit(prg->prog_used, i);
  110: 			prg->prog_cnum--;
  111: 			ret++;
  112: 		}
  113: 	pthread_mutex_unlock(&prg->prog_mtx);
  114: 
  115: 	return ret;
  116: }
  117: 
  118: /*
  119:  * io_progOpen() - Execute number of program(s)
  120:  *
  121:  * @prg = program pool
  122:  * @execNum = execute program(s) (0 max)
  123:  * return: 0 error, >0 executed programs and abs(<0) executed programs with logged error
  124:  */
  125: int
  126: io_progOpen(prog_t * __restrict prg, u_int execNum)
  127: {
  128: #ifdef POPEN_STREAM
  129: 	FILE *f;
  130: #else
  131: 	int f;
  132: #endif
  133: 	int stat, ret = 0;
  134: 	register int i;
  135: 	pid_t pid;
  136: 
  137: 	if (!prg)
  138: 		return 0;
  139: 	if (prg->prog_cnum + execNum > prg->prog_maxn) {
  140: 		io_SetErr(EINVAL, "Requested number for program execution is over pool's limit");
  141: 		return 0;
  142: 	}
  143: 
  144: 	pthread_mutex_lock(&prg->prog_mtx);
  145: 	for (i = 0; (execNum ? ret < execNum : 42) && i < array_Size(prg->prog_fds); i++)
  146: 		if (!array_Get(prg->prog_fds, i)) {
  147: 			f = e_popen(prg->prog_name, "r+", &pid);
  148: #ifdef POPEN_STREAM
  149: 			if (!f) {
  150: #else
  151: 			if (f == -1) {
  152: #endif
  153: 				LOGERR;
  154: 				ret = -1;
  155: 				break;
  156: 			} else if (waitpid(pid, &stat, WNOHANG)) {
  157: 				io_SetErr(ECHILD, "Program with pid=%d exit with status %d", 
  158: 						pid, WIFEXITED(stat) ? WEXITSTATUS(stat) : -1);
  159: 				ret = -1;
  160: 				break;
  161: 			} else
  162: 				array_Set(prg->prog_fds, i, f);
  163: 			prg->prog_cnum++;
  164: 			ret++;
  165: 		}
  166: 	pthread_mutex_unlock(&prg->prog_mtx);
  167: 
  168: 	return ret;
  169: }
  170: 
  171: /*
  172:  * io_progGrow() - Execute to number of programs in pool
  173:  *
  174:  * @prg = program pool
  175:  * @toNum = execute to number of programs (0 max)
  176:  * return: 0 error, >0 executed programs and abs(<0) executed programs with logged error
  177:  */
  178: int
  179: io_progGrow(prog_t * __restrict prg, u_int toNum)
  180: {
  181: 	if (!prg)
  182: 		return 0;
  183: 	if (toNum > prg->prog_maxn) {
  184: 		io_SetErr(EINVAL, "Requested number for program execution is over pool's limit");
  185: 		return 0;
  186: 	}
  187: 	if (!toNum)
  188: 		toNum = prg->prog_maxn;
  189: 
  190: 	return io_progOpen(prg, toNum - prg->prog_cnum);
  191: }
  192: 
  193: /*
  194:  * io_progVacuum() - Vacuum pool to running number of programs
  195:  *
  196:  * @prg = program pool
  197:  * @toNum = vacuum to number of programs (0 to init number)
  198:  * return: 0 error or >0 closed programs
  199:  */
  200: int
  201: io_progVacuum(prog_t * __restrict prg, u_int toNum)
  202: {
  203: 	register int i;
  204: 	int ret = 0;
  205: 
  206: 	if (!prg)
  207: 		return 0;
  208: 	if (toNum > prg->prog_maxn) {
  209: 		io_SetErr(EINVAL, "Requested number for close program is over pool's limit");
  210: 		return 0;
  211: 	}
  212: 	if (!toNum)
  213: 		toNum = prg->prog_inin;
  214: 
  215: 	pthread_mutex_lock(&prg->prog_mtx);
  216: 	for (i = array_Size(prg->prog_fds) - 1; prg->prog_cnum > toNum && i > -1; i--)
  217: 		if (array_Get(prg->prog_fds, i) && isclr(prg->prog_used, i)) {
  218: #ifdef POPEN_STREAM
  219: 			e_pclose(array(prg->prog_fds, i, FILE*));
  220: #else
  221: 			e_pclose((int) array(prg->prog_fds, i, intptr_t));
  222: #endif
  223: 			array_Del(prg->prog_fds, i, 0);
  224: 			prg->prog_cnum--;
  225: 			ret++;
  226: 		}
  227: 	pthread_mutex_unlock(&prg->prog_mtx);
  228: 
  229: 	return ret;
  230: }
  231: 
  232: /*
  233:  * io_progCheck() - Check exit status of program pool
  234:  *
  235:  * @prg = program pool
  236:  * return: -1 error or >-1 exited programs
  237:  */
  238: int
  239: io_progCheck(prog_t * __restrict prg)
  240: {
  241: 	int ret = 0;
  242: 	struct tagPIOPID *p;
  243: 	register int i;
  244: 
  245: 	if (!prg)
  246: 		return -1;
  247: 
  248: 	pthread_mutex_lock(&prg->prog_mtx);
  249: 	for (i = 0; i < array_Size(prg->prog_fds); i++)
  250: 		if (array_Get(prg->prog_fds, i) && 
  251: #ifdef POPEN_STREAM
  252: 				(p = pio_pgetpid(array(prg->prog_fds, i, FILE*))))
  253: #else
  254: 				(p = pio_pgetpid((int) array(prg->prog_fds, i, intptr_t))))
  255: #endif
  256: 			if (waitpid(p->pid, &p->stat, WNOHANG) > 0) {
  257: 				clrbit(prg->prog_used, i);
  258: 				ret++;
  259: 			}
  260: 	pthread_mutex_unlock(&prg->prog_mtx);
  261: 
  262: 	return ret;
  263: }
  264: 
  265: /*
  266:  * io_progAttach() - Attach to open program
  267:  *
  268:  * @prg = program pool
  269:  * return: NULL error or !=NULL attached program handle
  270:  */
  271: #ifdef POPEN_STREAM
  272: FILE *
  273: #else
  274: int
  275: #endif
  276: io_progAttach(prog_t * __restrict prg)
  277: {
  278: #ifdef POPEN_STREAM
  279: 	FILE *f = NULL;
  280: #else
  281: 	int f = -1;
  282: #endif
  283: 	register int i;
  284: 
  285: 	if (!prg)
  286: #ifdef POPEN_STREAM
  287: 		return NULL;
  288: #else
  289: 		return -1;
  290: #endif
  291: 
  292: 	pthread_mutex_lock(&prg->prog_mtx);
  293: 	for (i = 0; i < array_Size(prg->prog_fds); i++)
  294: 		if (array_Get(prg->prog_fds, i) && isclr(prg->prog_used, i)) {
  295: 			setbit(prg->prog_used, i);
  296: #ifdef POPEN_STREAM
  297: 			f = array(prg->prog_fds, i, FILE*);
  298: #else
  299: 			f = array(prg->prog_fds, i, intptr_t);
  300: #endif
  301: 			break;
  302: 		}
  303: 	pthread_mutex_unlock(&prg->prog_mtx);
  304: 
  305: 	return f;
  306: }
  307: 
  308: /*
  309:  * io_progDetach() - Detch from open program
  310:  *
  311:  * @prg= program pool
  312:  * @pfd = attached program handle
  313:  * return: none
  314:  */
  315: void
  316: #ifdef POPEN_STREAM
  317: io_progDetach(prog_t * __restrict prg, FILE *pfd)
  318: #else
  319: io_progDetach(prog_t * __restrict prg, int pfd)
  320: #endif
  321: {
  322: 	register int i;
  323: 
  324: 	if (!prg || !pfd)
  325: 		return;
  326: 
  327: 	pthread_mutex_lock(&prg->prog_mtx);
  328: 	for (i = 0; i < array_Size(prg->prog_fds); i++)
  329: #ifdef POPEN_STREAM
  330: 		if (array(prg->prog_fds, i, FILE*) == pfd) {
  331: #else
  332: 		if (array(prg->prog_fds, i, intptr_t) == pfd) {
  333: #endif
  334: 			clrbit(prg->prog_used, i);
  335: 			break;
  336: 		}
  337: 	pthread_mutex_unlock(&prg->prog_mtx);
  338: }

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