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>