1ZPROC(3) CZMQ Manual ZPROC(3)
2
3
4
6 zproc - Class for process configuration and status
7
9 // This is a draft class, and may change without notice. It is disabled in
10 // stable builds by default. If you use this in applications, please ask
11 // for it to be pushed to stable state. Use --enable-drafts to enable.
12 #ifdef CZMQ_BUILD_DRAFT_API
13 // *** Draft method, for development use, may change without warning ***
14 // Create a new zproc.
15 // NOTE: On Windows and with libzmq3 and libzmq2 this function
16 // returns NULL. Code needs to be ported there.
17 CZMQ_EXPORT zproc_t *
18 zproc_new (void);
19
20 // *** Draft method, for development use, may change without warning ***
21 // Destroy zproc, wait until process ends.
22 CZMQ_EXPORT void
23 zproc_destroy (zproc_t **self_p);
24
25 // *** Draft method, for development use, may change without warning ***
26 // Return command line arguments (the first item is the executable) or
27 // NULL if not set.
28 // Caller owns return value and must destroy it when done.
29 CZMQ_EXPORT zlist_t *
30 zproc_args (zproc_t *self);
31
32 // *** Draft method, for development use, may change without warning ***
33 // Setup the command line arguments, the first item must be an (absolute) filename
34 // to run.
35 CZMQ_EXPORT void
36 zproc_set_args (zproc_t *self, zlist_t **arguments);
37
38 // *** Draft method, for development use, may change without warning ***
39 // Setup the command line arguments, the first item must be an (absolute) filename
40 // to run. Variadic function, must be NULL terminated.
41 CZMQ_EXPORT void
42 zproc_set_argsx (zproc_t *self, const char *arguments, ...);
43
44 // *** Draft method, for development use, may change without warning ***
45 // Setup the environment variables for the process.
46 CZMQ_EXPORT void
47 zproc_set_env (zproc_t *self, zhash_t **arguments);
48
49 // *** Draft method, for development use, may change without warning ***
50 // Connects process stdin with a readable ('>', connect) zeromq socket. If
51 // socket argument is NULL, zproc creates own managed pair of inproc
52 // sockets. The writable one is then accessbile via zproc_stdin method.
53 CZMQ_EXPORT void
54 zproc_set_stdin (zproc_t *self, void *socket);
55
56 // *** Draft method, for development use, may change without warning ***
57 // Connects process stdout with a writable ('@', bind) zeromq socket. If
58 // socket argument is NULL, zproc creates own managed pair of inproc
59 // sockets. The readable one is then accessbile via zproc_stdout method.
60 CZMQ_EXPORT void
61 zproc_set_stdout (zproc_t *self, void *socket);
62
63 // *** Draft method, for development use, may change without warning ***
64 // Connects process stderr with a writable ('@', bind) zeromq socket. If
65 // socket argument is NULL, zproc creates own managed pair of inproc
66 // sockets. The readable one is then accessbile via zproc_stderr method.
67 CZMQ_EXPORT void
68 zproc_set_stderr (zproc_t *self, void *socket);
69
70 // *** Draft method, for development use, may change without warning ***
71 // Return subprocess stdin writable socket. NULL for
72 // not initialized or external sockets.
73 CZMQ_EXPORT void *
74 zproc_stdin (zproc_t *self);
75
76 // *** Draft method, for development use, may change without warning ***
77 // Return subprocess stdout readable socket. NULL for
78 // not initialized or external sockets.
79 CZMQ_EXPORT void *
80 zproc_stdout (zproc_t *self);
81
82 // *** Draft method, for development use, may change without warning ***
83 // Return subprocess stderr readable socket. NULL for
84 // not initialized or external sockets.
85 CZMQ_EXPORT void *
86 zproc_stderr (zproc_t *self);
87
88 // *** Draft method, for development use, may change without warning ***
89 // Starts the process, return just before execve/CreateProcess.
90 CZMQ_EXPORT int
91 zproc_run (zproc_t *self);
92
93 // *** Draft method, for development use, may change without warning ***
94 // process exit code
95 CZMQ_EXPORT int
96 zproc_returncode (zproc_t *self);
97
98 // *** Draft method, for development use, may change without warning ***
99 // PID of the process
100 CZMQ_EXPORT int
101 zproc_pid (zproc_t *self);
102
103 // *** Draft method, for development use, may change without warning ***
104 // return true if process is running, false if not yet started or finished
105 CZMQ_EXPORT bool
106 zproc_running (zproc_t *self);
107
108 // *** Draft method, for development use, may change without warning ***
109 // wait or poll process status, return return code
110 CZMQ_EXPORT int
111 zproc_wait (zproc_t *self, bool hang);
112
113 // *** Draft method, for development use, may change without warning ***
114 // return internal actor, usefull for the polling if process died
115 CZMQ_EXPORT void *
116 zproc_actor (zproc_t *self);
117
118 // *** Draft method, for development use, may change without warning ***
119 // send a signal to the subprocess
120 CZMQ_EXPORT void
121 zproc_kill (zproc_t *self, int signal);
122
123 // *** Draft method, for development use, may change without warning ***
124 // set verbose mode
125 CZMQ_EXPORT void
126 zproc_set_verbose (zproc_t *self, bool verbose);
127
128 // *** Draft method, for development use, may change without warning ***
129 // Self test of this class.
130 CZMQ_EXPORT void
131 zproc_test (bool verbose);
132
133 #endif // CZMQ_BUILD_DRAFT_API
134 Please add '@interface' section in './../src/zproc.c'.
135
137 zproc - process configuration and status, plus unix pipes on steroids
138
139 Warning
140 zproc class have several limitations atm * is tested on zmq4 on
141 Linux and OSX. * does not work on Windows, where you get empty
142 stubs for most of the methods * does not work on libzmq3 and
143 libzmq2. We have experienced stalls and timeouts when running tests
144 against such old version
145
146 Note: zproc is not yet stable, so there are no guarantees regarding API
147 stability. Some methods can have weird semantics or strange API.
148
149 Class zproc run an external process and to use ZeroMQ sockets to
150 communicate with it. In other words standard input and outputs MAY be
151 connected with appropriate zeromq socket and data flow is managed by
152 zproc itself. This makes zproc the best in class way how to run and
153 manage sub processes.
154
155 Data are sent and received as zframes (zframe_t), so zproc does not try
156 to interpret content of the messages in any way. See test example on
157 how to use it.
158
159 +----------------------------------------+
160 | /bin/cat cat /etc/passwd |
161 | stdin | stdout | stderr |
162 |------||--------||---------------||-----|
163 | fd1 fd2 fd3 |
164 | ^ v v |
165 |zmq://stdin |zmq://stdout |zmq://stderr |
166 | [zproc supervisor] |
167 +----------------------------------------+
168
169 ----------> zeromq magic here <-----------
170
171 +----------------------------------------+
172 |zmq://stdin |zmq://stdout |zmq://stderr |
173 | |
174 | consumer |
175 | |
176 | |
177 +----------------------------------------+
178
179 Please add @discuss section in ./../src/zproc.c.
180
182 From zproc_test method.
183
184 // variable file contains path to zsp executable:
185 // char *file = "path/to/zsp";
186
187 #if defined (__WINDOWS__)
188 printf ("Very limited (on Windows) ");
189 {
190 zsys_init ();
191 zproc_t *self = zproc_new ();
192 assert (self);
193
194 zproc_set_verbose (self, verbose);
195 zproc_set_argsx (self, file, "-v", NULL);
196 zproc_run (self);
197 zclock_sleep (100); // to let actor start the process
198 assert (zproc_pid (self));
199
200 zproc_kill (self, SIGTERM);
201 assert (zproc_returncode (self) == 255);
202 zproc_destroy (&self);
203 }
204 printf ("OK\n");
205 return;
206 #endif
207 // Test case #1: run command, wait until it ends and get the (stdandard) output
208 zproc_t *self = zproc_new ();
209 assert (self);
210 zproc_set_verbose (self, verbose);
211
212 // join stdout of the process to zeromq socket
213 // all data will be readable from zproc_stdout socket
214 assert (!zproc_stdout (self));
215 zproc_set_stdout (self, NULL);
216 assert (zproc_stdout (self));
217
218 zproc_set_argsx (self, file, "--help", NULL);
219
220 if (verbose)
221 zsys_debug("zproc_test() : launching helper '%s' --help", file );
222
223 int r = zproc_run (self);
224 assert (r == 0);
225 zframe_t *frame;
226 zsock_brecv (zproc_stdout (self), "f", &frame);
227 assert (frame);
228 assert (zframe_data (frame));
229 // TODO: real test
230 if (verbose)
231 zframe_print (frame, "1:");
232 zframe_destroy (&frame);
233 r = zproc_wait (self, true);
234 assert (r == 0);
235 zproc_destroy (&self);
236
237 // Test case #2: use never ending subprocess and poller to read data from it
238 // Create new zproc instance
239 self = zproc_new ();
240 zproc_set_verbose (self, verbose);
241 assert (self);
242 // join stdout of the process to zeromq socket
243 // all data will be readable from zproc_stdout socket
244 zproc_set_stdout (self, NULL);
245
246 zlist_t *args = zlist_new ();
247 zlist_autofree (args);
248 zlist_append (args, file);
249 zlist_append (args, "--stdout");
250 zproc_set_args (self, &args);
251
252 zhash_t *env = zhash_new ();
253 zhash_autofree (env);
254 zhash_insert (env, "ZSP_MESSAGE", "czmq is great\n");
255 zproc_set_env (self, &env);
256
257 // execute the binary. It runs in own actor, which monitor the process and
258 // pass data accross pipes and zeromq sockets
259 if (verbose)
260 zsys_debug("zproc_test() : launching helper '%s'", file );
261 zproc_run (self);
262 zpoller_t *poller = zpoller_new (zproc_stdout (self), NULL);
263
264 // kill the binary, it never ends, but the test must:
265 // termination also flushes the output streams so we can
266 // read them entirely; note that other process runs in
267 // parallel to this thread
268 if (verbose)
269 zsys_debug("zproc_test() : sleeping 4000 msec to gather some output from helper");
270 zclock_sleep (4000);
271 zproc_kill (self, SIGTERM);
272 zproc_wait (self, true);
273
274 // read the content from zproc_stdout - use zpoller and a loop
275 bool stdout_read = false;
276 int64_t zproc_timeout_msec = 10000;
277 int64_t zproc_test_start_msec = zclock_mono();
278 int64_t zproc_test_elapsed_msec = 0;
279
280 while (!zsys_interrupted) {
281 void *which = zpoller_wait (poller, 800);
282 zproc_test_elapsed_msec = zclock_mono() - zproc_test_start_msec;
283
284 if (!which) {
285 if (stdout_read) {
286 if (verbose)
287 zsys_debug("zproc_test() : did not get stdout from helper, but we already have some (%" PRIi64 " msec remaining to retry)", (zproc_timeout_msec - zproc_test_elapsed_msec) );
288 break;
289 }
290 if (zproc_timeout_msec > zproc_test_elapsed_msec) {
291 if (verbose)
292 zsys_debug("zproc_test() : did not get stdout from helper, %" PRIi64 " msec remaining to retry", (zproc_timeout_msec - zproc_test_elapsed_msec) );
293 continue;
294 }
295 // ...else : we've slept a lot and got no response; kill the helper
296 if (verbose)
297 zsys_debug("zproc_test() : did not get stdout from helper, patience expired (%" PRIi64 " msec remaining to retry)", (zproc_timeout_msec - zproc_test_elapsed_msec) );
298 break;
299 }
300
301 if (which == zproc_stdout (self)) {
302 // it suffices for us to have read something
303 // we only check the first frame, others may start with the
304 // expected key string broken mid-way due to alignment etc.,
305 // but we drain the whole incoming queue of stdout frames.
306 zframe_t *frame;
307 zsock_brecv (zproc_stdout (self), "f", &frame);
308 assert (frame);
309 assert (zframe_data (frame));
310 if (!stdout_read) {
311 if (verbose)
312 zsys_debug("zproc_test() : got stdout from helper, %" PRIi64 " msec was remaining to retry", (zproc_timeout_msec - zproc_test_elapsed_msec));
313 assert (!strncmp(
314 "czmq is great\n",
315 (char*) zframe_data (frame),
316 14));
317 stdout_read = true;
318 }
319
320 if (verbose)
321 zframe_print (frame, "zproc_test");
322
323 zframe_destroy (&frame);
324 continue;
325 }
326
327 // should not get there
328 if (verbose)
329 zsys_debug("zproc_test() : reached the unreachable point (unexpected zpoller result), %" PRIi64 " msec was remaining to retry", (zproc_timeout_msec - zproc_test_elapsed_msec) );
330 assert (false);
331 }
332
333 assert (stdout_read);
334 zpoller_destroy (&poller);
335 zproc_destroy (&self);
336
337
339 The czmq manual was written by the authors in the AUTHORS file.
340
342 Main web site:
343
344 Report bugs to the email <zeromq-dev@lists.zeromq.org[1]>
345
347 Copyright (c) the Contributors as noted in the AUTHORS file. This file
348 is part of CZMQ, the high-level C binding for 0MQ:
349 http://czmq.zeromq.org. This Source Code Form is subject to the terms
350 of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
351 distributed with this file, You can obtain one at
352 http://mozilla.org/MPL/2.0/. LICENSE included with the czmq
353 distribution.
354
356 1. zeromq-dev@lists.zeromq.org
357 mailto:zeromq-dev@lists.zeromq.org
358
359
360
361CZMQ 4.1.1 07/24/2019 ZPROC(3)