ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/unix_process.c
Revision: 3.13
Committed: Fri Mar 24 12:56:12 2017 UTC (7 years, 1 month ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad5R2, rad5R1
Changes since 3.12: +3 -2 lines
Log Message:
Added case for already closed process in list

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: unix_process.c,v 3.12 2016/03/04 19:16:49 greg Exp $";
3 #endif
4 /*
5 * Routines to communicate with separate process via dual pipes
6 * Unix version
7 *
8 * External symbols declared in standard.h
9 */
10
11 #include "copyright.h"
12
13 #include <sys/types.h>
14 #include <sys/wait.h>
15 #include <fcntl.h>
16 #include <stdlib.h>
17
18 #include "rtprocess.h"
19 #include "rtio.h"
20
21
22 int
23 open_process( /* open communication to separate process */
24 SUBPROC *pd,
25 char *av[]
26 )
27 {
28 char *compath;
29 int p0[2], p1[2];
30
31 pd->pid = -1;
32 pd->running = 0; /* not going yet */
33
34 if (av == NULL) /* cloning operation? */
35 compath = NULL;
36 else if ((compath = getpath(av[0], getenv("PATH"), X_OK)) == NULL)
37 return(0);
38 if (pipe(p0) < 0 || pipe(p1) < 0)
39 return(-1);
40 if ((pd->pid = fork()) == 0) { /* if child... */
41 close(p0[1]);
42 close(p1[0]);
43 if (p0[0] != 0) { /* connect p0 to stdin */
44 dup2(p0[0], 0);
45 close(p0[0]);
46 }
47 if (p1[1] != 1) { /* connect p1 to stdout */
48 dup2(p1[1], 1);
49 close(p1[1]);
50 }
51 if (compath == NULL) /* just cloning? */
52 return(0);
53 execv(compath, av); /* else exec command */
54 perror(compath);
55 _exit(127);
56 }
57 if (pd->pid == -1)
58 return(-1);
59 close(p0[0]);
60 close(p1[1]);
61 pd->r = p1[0];
62 pd->w = p0[1];
63 /*
64 * Close write stream on exec to avoid multiprocessing deadlock.
65 * No use in read stream without it, so set flag there as well.
66 * GW: This bug took me two days to figure out!!
67 */
68 fcntl(pd->r, F_SETFD, FD_CLOEXEC);
69 fcntl(pd->w, F_SETFD, FD_CLOEXEC);
70 pd->running = 1;
71 return(PIPE_BUF);
72 }
73
74
75 int
76 close_processes( /* close pipes and wait for processes to finish */
77 SUBPROC pd[],
78 int nproc
79 )
80 {
81 int togo = nproc;
82 int status, rtn_status = 0;
83 RT_PID pid;
84 int i;
85
86 for (i = 0; i < nproc; i++) /* close pipes, first */
87 if (pd[i].running) {
88 close(pd[i].w);
89 close(pd[i].r);
90 pd[i].running = 0;
91 } else
92 togo -= (pd[i].pid < 0);
93 if (nproc == 1) { /* await specific process? */
94 if (waitpid(pd->pid, &status, 0) != pd->pid)
95 return(-1);
96 pd->pid = -1;
97 return(status>>8 & 0xff);
98 }
99 /* else unordered wait */
100 while (togo > 0 && (pid = wait(&status)) >= 0) {
101 for (i = nproc; i-- > 0; )
102 if (pd[i].pid == pid) {
103 pd[i].pid = -1;
104 --togo;
105 break;
106 }
107 if (i < 0)
108 continue; /* child we don't know? */
109 status = status>>8 & 0xff;
110 if (status) /* record non-zero status */
111 rtn_status = status;
112 }
113 if (togo) /* child went missing? */
114 return(-1);
115 return(rtn_status);
116 }