Annotation of libaitio/src/exec.c, revision 1.1.2.19
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.18 misho 176: * io_progOpen2() - Start program from pool on first unused slot
177: *
178: * @prg = program pool
179: * return: -1 error, >-1 reside at slot
180: */
181: int
182: io_progOpen2(prog_t * __restrict prg)
183: {
184: #ifdef POPEN_STREAM
185: FILE *f = NULL;
186: #else
187: int f = -1;
188: #endif
189: int stat, ret = -1;
190: register int i;
191: pid_t pid;
192:
193: if (!prg)
194: return -1;
195: if (prg->prog_cnum + 1 > prg->prog_maxn) {
196: io_SetErr(EINVAL, "Requested number for program execution is over pool's limit");
197: return -1;
198: }
199:
200: pthread_mutex_lock(&prg->prog_mtx);
201: for (i = 0; i < array_Size(prg->prog_fds); i++)
202: if (!array_Get(prg->prog_fds, i)) {
203: f = e_popen(prg->prog_name, "r+", &pid);
204: #ifdef POPEN_STREAM
205: if (!f) {
206: #else
207: if (f == -1) {
208: #endif
209: LOGERR;
210: break;
211: } else if (waitpid(pid, &stat, WNOHANG)) {
212: io_SetErr(ECHILD, "Program with pid=%d exit with status %d",
213: pid, WIFEXITED(stat) ? WEXITSTATUS(stat) : -1);
214: e_pclose(f);
215: break;
216: } else
217: array_Set(prg->prog_fds, i, f);
218: clrbit(prg->prog_used, i);
219: prg->prog_cnum++;
220: ret = i;
221: break;
222: }
223: pthread_mutex_unlock(&prg->prog_mtx);
224:
225: return ret;
226: }
227:
228: /*
1.1.2.1 misho 229: * io_progOpen() - Execute number of program(s)
230: *
231: * @prg = program pool
232: * @execNum = execute program(s) (0 max)
1.1.2.18 misho 233: * return: -1 error, >0 executed programs
1.1.2.1 misho 234: */
235: int
236: io_progOpen(prog_t * __restrict prg, u_int execNum)
237: {
1.1.2.11 misho 238: #ifdef POPEN_STREAM
1.1.2.1 misho 239: FILE *f;
1.1.2.11 misho 240: #else
241: int f;
242: #endif
1.1.2.4 misho 243: int stat, ret = 0;
1.1.2.1 misho 244: register int i;
1.1.2.4 misho 245: pid_t pid;
1.1.2.1 misho 246:
247: if (!prg)
1.1.2.18 misho 248: return -1;
1.1.2.8 misho 249: if (prg->prog_cnum + execNum > prg->prog_maxn) {
1.1.2.1 misho 250: io_SetErr(EINVAL, "Requested number for program execution is over pool's limit");
1.1.2.18 misho 251: return -1;
1.1.2.1 misho 252: }
253:
254: pthread_mutex_lock(&prg->prog_mtx);
255: for (i = 0; (execNum ? ret < execNum : 42) && i < array_Size(prg->prog_fds); i++)
256: if (!array_Get(prg->prog_fds, i)) {
1.1.2.19! misho 257: printf("%d) %s!!! %d ret=%d\n", i, __func__, execNum, ret);
1.1.2.6 misho 258: f = e_popen(prg->prog_name, "r+", &pid);
1.1.2.11 misho 259: #ifdef POPEN_STREAM
1.1.2.1 misho 260: if (!f) {
1.1.2.11 misho 261: #else
262: if (f == -1) {
263: #endif
1.1.2.1 misho 264: LOGERR;
1.1.2.5 misho 265: ret = -1;
1.1.2.1 misho 266: break;
1.1.2.6 misho 267: } else if (waitpid(pid, &stat, WNOHANG)) {
268: io_SetErr(ECHILD, "Program with pid=%d exit with status %d",
269: pid, WIFEXITED(stat) ? WEXITSTATUS(stat) : -1);
1.1.2.18 misho 270: e_pclose(f);
1.1.2.5 misho 271: ret = -1;
1.1.2.4 misho 272: break;
1.1.2.1 misho 273: } else
274: array_Set(prg->prog_fds, i, f);
1.1.2.15 misho 275: clrbit(prg->prog_used, i);
1.1.2.1 misho 276: prg->prog_cnum++;
277: ret++;
278: }
279: pthread_mutex_unlock(&prg->prog_mtx);
280:
281: return ret;
282: }
283:
284: /*
1.1.2.8 misho 285: * io_progGrow() - Execute to number of programs in pool
286: *
287: * @prg = program pool
288: * @toNum = execute to number of programs (0 max)
1.1.2.17 misho 289: * return: 0 error or nothing to do,
290: * >0 executed programs and abs(<0) executed programs with logged error
1.1.2.8 misho 291: */
292: int
293: io_progGrow(prog_t * __restrict prg, u_int toNum)
294: {
295: if (!prg)
296: return 0;
297: if (toNum > prg->prog_maxn) {
298: io_SetErr(EINVAL, "Requested number for program execution is over pool's limit");
299: return 0;
300: }
301: if (!toNum)
302: toNum = prg->prog_maxn;
1.1.2.17 misho 303: if (toNum < prg->prog_inin)
304: toNum = prg->prog_inin;
305:
1.1.2.19! misho 306: if ((int) (toNum - prg->prog_cnum) < 1)
1.1.2.17 misho 307: return 0;
1.1.2.8 misho 308:
309: return io_progOpen(prg, toNum - prg->prog_cnum);
310: }
311:
312: /*
1.1.2.1 misho 313: * io_progVacuum() - Vacuum pool to running number of programs
314: *
315: * @prg = program pool
316: * @toNum = vacuum to number of programs (0 to init number)
317: * return: 0 error or >0 closed programs
318: */
319: int
320: io_progVacuum(prog_t * __restrict prg, u_int toNum)
321: {
322: register int i;
323: int ret = 0;
1.1.2.14 misho 324: struct tagPIOPID *p;
1.1.2.1 misho 325:
326: if (!prg)
327: return 0;
328: if (toNum > prg->prog_maxn) {
329: io_SetErr(EINVAL, "Requested number for close program is over pool's limit");
330: return 0;
331: }
332: if (!toNum)
333: toNum = prg->prog_inin;
334:
335: pthread_mutex_lock(&prg->prog_mtx);
336: for (i = array_Size(prg->prog_fds) - 1; prg->prog_cnum > toNum && i > -1; i--)
1.1.2.14 misho 337: if (array_Get(prg->prog_fds, i) && isclr(prg->prog_used, i) &&
1.1.2.11 misho 338: #ifdef POPEN_STREAM
1.1.2.14 misho 339: (p = pio_pgetpid(array(prg->prog_fds, i, FILE*)))) {
340: kill(p->pid, SIGTERM);
341: usleep(1000);
342: if (waitpid(p->pid, &p->stat, WNOHANG) > 0)
343: kill(p->pid, SIGKILL);
1.1.2.6 misho 344: e_pclose(array(prg->prog_fds, i, FILE*));
1.1.2.11 misho 345: #else
1.1.2.14 misho 346: (p = pio_pgetpid((int) array(prg->prog_fds, i, intptr_t)))) {
347: kill(p->pid, SIGTERM);
348: usleep(1000);
349: if (waitpid(p->pid, &p->stat, WNOHANG) > 0)
350: kill(p->pid, SIGKILL);
1.1.2.11 misho 351: e_pclose((int) array(prg->prog_fds, i, intptr_t));
352: #endif
1.1.2.1 misho 353: array_Del(prg->prog_fds, i, 0);
354: prg->prog_cnum--;
355: ret++;
356: }
357: pthread_mutex_unlock(&prg->prog_mtx);
358:
359: return ret;
360: }
1.1.2.7 misho 361:
362: /*
363: * io_progCheck() - Check exit status of program pool
364: *
365: * @prg = program pool
1.1.2.18 misho 366: * @re = resurrect program to init number
1.1.2.7 misho 367: * return: -1 error or >-1 exited programs
368: */
369: int
1.1.2.15 misho 370: io_progCheck(prog_t * __restrict prg, int re)
1.1.2.7 misho 371: {
372: int ret = 0;
373: struct tagPIOPID *p;
374: register int i;
375:
376: if (!prg)
377: return -1;
378:
1.1.2.9 misho 379: pthread_mutex_lock(&prg->prog_mtx);
1.1.2.7 misho 380: for (i = 0; i < array_Size(prg->prog_fds); i++)
381: if (array_Get(prg->prog_fds, i) &&
1.1.2.11 misho 382: #ifdef POPEN_STREAM
1.1.2.7 misho 383: (p = pio_pgetpid(array(prg->prog_fds, i, FILE*))))
1.1.2.11 misho 384: #else
385: (p = pio_pgetpid((int) array(prg->prog_fds, i, intptr_t))))
386: #endif
1.1.2.9 misho 387: if (waitpid(p->pid, &p->stat, WNOHANG) > 0) {
388: clrbit(prg->prog_used, i);
1.1.2.15 misho 389: #ifdef POPEN_STREAM
390: e_pclose(array(prg->prog_fds, i, FILE*));
391: #else
392: e_pclose((int) array(prg->prog_fds, i, intptr_t));
393: #endif
394: array_Del(prg->prog_fds, i, 0);
395: prg->prog_cnum--;
1.1.2.7 misho 396: ret++;
1.1.2.9 misho 397: }
398: pthread_mutex_unlock(&prg->prog_mtx);
1.1.2.7 misho 399:
1.1.2.18 misho 400: /* resurrect to init number */
1.1.2.19! misho 401: if (re && ((int) (prg->prog_inin - prg->prog_cnum) > 0))
1.1.2.17 misho 402: io_progOpen(prg, prg->prog_inin - prg->prog_cnum);
1.1.2.15 misho 403:
1.1.2.7 misho 404: return ret;
405: }
1.1.2.9 misho 406:
407: /*
408: * io_progAttach() - Attach to open program
409: *
410: * @prg = program pool
1.1.2.16 misho 411: * @newOne = Execute new one program after attach
1.1.2.9 misho 412: * return: NULL error or !=NULL attached program handle
413: */
1.1.2.11 misho 414: #ifdef POPEN_STREAM
1.1.2.9 misho 415: FILE *
1.1.2.11 misho 416: #else
417: int
418: #endif
1.1.2.16 misho 419: io_progAttach(prog_t * __restrict prg, int newOne)
1.1.2.9 misho 420: {
1.1.2.11 misho 421: #ifdef POPEN_STREAM
1.1.2.9 misho 422: FILE *f = NULL;
1.1.2.11 misho 423: #else
424: int f = -1;
425: #endif
1.1.2.9 misho 426: register int i;
427:
428: if (!prg)
1.1.2.11 misho 429: #ifdef POPEN_STREAM
1.1.2.9 misho 430: return NULL;
1.1.2.11 misho 431: #else
432: return -1;
433: #endif
1.1.2.9 misho 434:
435: pthread_mutex_lock(&prg->prog_mtx);
436: for (i = 0; i < array_Size(prg->prog_fds); i++)
437: if (array_Get(prg->prog_fds, i) && isclr(prg->prog_used, i)) {
438: setbit(prg->prog_used, i);
1.1.2.11 misho 439: #ifdef POPEN_STREAM
1.1.2.9 misho 440: f = array(prg->prog_fds, i, FILE*);
1.1.2.11 misho 441: #else
442: f = array(prg->prog_fds, i, intptr_t);
443: #endif
1.1.2.9 misho 444: break;
445: }
446: pthread_mutex_unlock(&prg->prog_mtx);
447:
1.1.2.19! misho 448: /* not found free program */
1.1.2.18 misho 449: if (!f && (i = io_progOpen2(prg)) > 0) {
450: #ifdef POPEN_STREAM
451: f = array(prg->prog_fds, i, FILE*);
452: #else
453: f = array(prg->prog_fds, i, intptr_t);
454: #endif
455: }
456:
1.1.2.16 misho 457: /* execute new one program */
458: if (newOne && f)
459: io_progOpen(prg, 1);
460:
1.1.2.9 misho 461: return f;
462: }
463:
464: /*
465: * io_progDetach() - Detch from open program
466: *
467: * @prg= program pool
468: * @pfd = attached program handle
469: * return: none
470: */
471: void
1.1.2.11 misho 472: #ifdef POPEN_STREAM
1.1.2.9 misho 473: io_progDetach(prog_t * __restrict prg, FILE *pfd)
1.1.2.11 misho 474: #else
475: io_progDetach(prog_t * __restrict prg, int pfd)
476: #endif
1.1.2.9 misho 477: {
478: register int i;
479:
480: if (!prg || !pfd)
481: return;
482:
483: pthread_mutex_lock(&prg->prog_mtx);
484: for (i = 0; i < array_Size(prg->prog_fds); i++)
1.1.2.11 misho 485: #ifdef POPEN_STREAM
1.1.2.9 misho 486: if (array(prg->prog_fds, i, FILE*) == pfd) {
1.1.2.11 misho 487: #else
488: if (array(prg->prog_fds, i, intptr_t) == pfd) {
489: #endif
1.1.2.9 misho 490: clrbit(prg->prog_used, i);
491: break;
492: }
493: pthread_mutex_unlock(&prg->prog_mtx);
494: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>