ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/rtprocess.h
Revision: 3.23
Committed: Wed Apr 7 01:15:53 2021 UTC (3 years ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad5R4, HEAD
Changes since 3.22: +2 -2 lines
Log Message:
docs: fixed comment

File Contents

# Content
1 /* RCSid $Id: rtprocess.h,v 3.22 2021/01/19 18:15:32 greg Exp $ */
2 /*
3 * rtprocess.h
4 * Routines to communicate with separate process via dual pipes
5 *
6 * WARNING: On Windows, there's a system header named <process.h>.
7 */
8 #ifndef _RAD_PROCESS_H_
9 #define _RAD_PROCESS_H_
10
11 #include <errno.h>
12 #include "paths.h"
13 #if defined(_WIN32) || defined(_WIN64)
14 #include <windows.h> /* DWORD etc. */
15 typedef DWORD RT_PID;
16 #include <process.h> /* getpid() and others */
17 #define getpid _getpid
18 #define execv _execv
19 #define execvp _execvp
20 #ifdef _MSC_VER
21 #include <BaseTsd.h>
22 typedef SSIZE_T ssize_t;
23 #endif
24 #else
25 typedef pid_t RT_PID;
26 #endif
27
28
29 #ifdef __cplusplus
30 extern "C" {
31 #endif
32
33 /* On Windows, a process ID is a DWORD. That might actually be the
34 same thing as an int, but it's better not to assume anything.
35
36 This means that we shouldn't rely on PIDs and file descriptors
37 being the same type, so we have to describe processes with a struct,
38 instead of the original int[3]. For that purpose, we typedef a
39 platform independent RT_PID.
40 */
41
42 /* On Unix, we can set flags and assign descriptors before opening a
43 process, coupling an existing input or output to the new process rather
44 than opening both pipes. If PF_FILT_INP is passed in the flags member of
45 SUBPROC, then the given r stream will be attached to the standard input
46 of the child process, and subsequent reads from that descriptor in the
47 parent get data from the standard output of the child, instead. The
48 returned w descriptor is set to -1, since there is no longer any way
49 to write to the input of the child. The default r descriptor of 0 will
50 compel the child to act as a filter on the standard input of the parent.
51 Whatever r handle you specify, the child will filter its read operations.
52 Note that this should be called before anything has been buffered using r.
53 If PF_FILT_OUT is set in flags, then the given w stream will be
54 attached to the standard output of the child, and subsequent writes
55 to that descriptor in the parent send data to the standard input
56 of the child. The returned r descriptor is set to -1, since
57 there is no longer any output to read from the child. The
58 default w descriptor of 1 will cause the child to act as a filter
59 on the output of the parent. Make sure to call fflush(stdout) first
60 if any data was buffered. It is illegal to set both PF_FILT_INP and
61 PF_FILT_OUT, as a circular process is guaranteed to hang.
62
63 If you want behavior similar to popen(cmd, "w") (again Unix-only),
64 keeping stdout open in parent, use a duplicate descriptor like so:
65 {
66 SUBPROC rtp = sp_inactive;
67 FILE *fout;
68 fflush(stdout);
69 rtp.w = dup(fileno(stdout));
70 rtp.flags |= PF_FILT_OUT;
71 if (open_process(&rtp, cmd_argv) <= 0) {
72 perror(cmd_argv[0]); exit(1);
73 }
74 fout = fdopen(rtp.w, "w");
75 ...write data to filter using fout until finished...
76 fclose(fout);
77 if (close_process(&rtp)) {
78 perror(cmd_argv[0]); exit(1);
79 }
80 ...can continue sending data directly to stdout...
81 }
82 We could also have called open_process() after fdopen() above, or after
83 using fopen() on a file if we wanted to insert our filter before it.
84 A similar sequence may be used to filter from stdin without closing
85 it, though process termination becomes more difficult with two readers.
86 Filtering input from a file works better, since the file is then read by
87 the child only, as in:
88 {
89 SUBPROC rtp = sp_inactive;
90 FILE *fin = fopen(fname, "r");
91 if (fin == NULL) {
92 open_error(fname); exit(1);
93 }
94 rtp.r = fileno(fin);
95 rtp.flags |= PF_FILT_INP;
96 if (open_process(&rtp, cmd_argv) <= 0) {
97 perror(cmd_argv[0]); fclose(fin); exit(1);
98 }
99 ...read filtered file data from fin until EOF...
100 fclose(fin);
101 if (close_process(&rtp)) {
102 perror(cmd_argv[0]); exit(1);
103 }
104 }
105 */
106
107
108 #ifndef PIPE_BUF
109 #ifdef PIPSIZ
110 #define PIPE_BUF PIPSIZ
111 #else
112 #ifdef PIPE_MAX
113 #define PIPE_BUF PIPE_MAX
114 #else
115 #define PIPE_BUF 512 /* hyperconservative */
116 #endif
117 #endif
118 #endif
119 /* process flags */
120 #define PF_RUNNING 1 /* process is running */
121 #define PF_FILT_INP 2 /* use assigned read descriptor */
122 #define PF_FILT_OUT 4 /* use assigned write descriptor */
123
124 typedef struct {
125 int flags; /* what is being done */
126 int r; /* read handle */
127 int w; /* write handle */
128 RT_PID pid; /* process ID */
129 } SUBPROC;
130
131 #define SP_INACTIVE {0,0,1,-1} /* for static initializations */
132
133 #define close_process(pd) close_processes(pd,1)
134
135 extern int open_process(SUBPROC *pd, char *av[]);
136 extern int close_processes(SUBPROC pd[], int nproc);
137 extern int process(SUBPROC *pd, char *recvbuf, char *sendbuf, int nbr, int nbs);
138 extern ssize_t readbuf(int fd, char *bpos, ssize_t siz);
139 extern ssize_t writebuf(int fd, char *bpos, ssize_t siz);
140
141 #if defined(_WIN32) || defined(_WIN64)
142 /* any non-negative increment will send the process to IDLE_PRIORITY_CLASS. */
143 extern int win_kill(RT_PID pid, int sig /* ignored */);
144 extern int win_nice(int inc);
145 #endif
146
147 extern SUBPROC sp_inactive;
148
149 #ifdef __cplusplus
150 }
151 #endif
152 #endif /* _RAD_PROCESS_H_ */
153