diff options
author | Tuan Hoang <tmhoang@linux.vnet.ibm.com> | 2019-01-29 14:08:13 +0100 |
---|---|---|
committer | Natanael Copa <ncopa@alpinelinux.org> | 2019-03-22 15:59:14 +0000 |
commit | fd5c3e8fc14612619e0a2377b61d041bc1648661 (patch) | |
tree | bf21398f3eea1dd30bffe1fed8b2f44554e75f57 /main/czmq | |
parent | 4cb8975d681d58e58724e0354b101cbc2a0e7dbb (diff) | |
download | aports-fd5c3e8fc14612619e0a2377b61d041bc1648661.tar.bz2 aports-fd5c3e8fc14612619e0a2377b61d041bc1648661.tar.xz |
main/czmq: backport from master to fix tests on s390x
zproc/zsp tests seem to be fixed in master
zdigest and SHA1 functions fail when building with CMake
Use normal/official build scripts instead
Diffstat (limited to 'main/czmq')
-rw-r--r-- | main/czmq/APKBUILD | 31 | ||||
-rw-r--r-- | main/czmq/zproc_zsp.patch | 768 |
2 files changed, 786 insertions, 13 deletions
diff --git a/main/czmq/APKBUILD b/main/czmq/APKBUILD index e4afa86266..2b018f8bca 100644 --- a/main/czmq/APKBUILD +++ b/main/czmq/APKBUILD @@ -2,31 +2,35 @@ # Maintainer: Jakub Jirutka <jakub@jirutka.cz> pkgname=czmq pkgver=4.1.1 -pkgrel=0 +pkgrel=1 pkgdesc="High-level C binding for ZeroMQ" url="http://czmq.zeromq.org/" -arch="all !s390x" # zproxy test timeouts on s390x +arch="all" license="MPL-2.0" depends_dev="util-linux-dev zeromq-dev" -makedepends="$depends_dev cmake" +makedepends="$depends_dev libtool autoconf automake" subpackages="$pkgname-dev" -source="$pkgname-$pkgver.tar.gz::https://github.com/zeromq/$pkgname/archive/v$pkgver.tar.gz" +source="$pkgname-$pkgver.tar.gz::https://github.com/zeromq/$pkgname/archive/v$pkgver.tar.gz + zproc_zsp.patch + " builddir="$srcdir/$pkgname-$pkgver" +prepare() { + default_prepare + cd "$builddir" + ./autogen.sh +} build() { cd "$builddir" - - # Note: One test segfaults when built with MinSizeRel (-Os). - cmake \ - -DCMAKE_BUILD_TYPE=Release \ - -DCMAKE_INSTALL_PREFIX=/usr \ - -DCMAKE_VERBOSE_MAKEFILE=ON - make + ./configure \ + --prefix=/usr \ + --with-libsystemd=no + make -j1 } check() { cd "$builddir" - make test + make -j1 check } package() { @@ -34,4 +38,5 @@ package() { make install DESTDIR="$pkgdir" } -sha512sums="c36d509e154a2142154f339294375bab0f6a2752f025a4489067bbddb22c4ef8f8e501797e755ac3779aa5c1c19397d32f7195ba80ae6b81e349f22c7634fb91 czmq-4.1.1.tar.gz" +sha512sums="c36d509e154a2142154f339294375bab0f6a2752f025a4489067bbddb22c4ef8f8e501797e755ac3779aa5c1c19397d32f7195ba80ae6b81e349f22c7634fb91 czmq-4.1.1.tar.gz +647c4915220f8e668750495b7511b60e8cf67b677de920176905797d76ed6fad7b63c5cc930a6635f77fb9c0c28427f7c6662df5de18e91412c3c76dde43e6a9 zproc_zsp.patch" diff --git a/main/czmq/zproc_zsp.patch b/main/czmq/zproc_zsp.patch new file mode 100644 index 0000000000..00ddc06311 --- /dev/null +++ b/main/czmq/zproc_zsp.patch @@ -0,0 +1,768 @@ +Backport from git master at: +1a6a8b1f50610e59bd12b63f7dc409f8c11ee79a + + +diff --git a/include/zproc.h b/include/zproc.h +index 6762d72..7e13420 100644 +--- a/include/zproc.h ++++ b/include/zproc.h +@@ -122,12 +122,19 @@ CZMQ_EXPORT bool + zproc_running (zproc_t *self); + + // *** Draft method, for development use, may change without warning *** ++// The timeout should be zero or greater, or -1 to wait indefinitely. + // wait or poll process status, return return code + CZMQ_EXPORT int +- zproc_wait (zproc_t *self, bool hang); ++ zproc_wait (zproc_t *self, int timeout); + + // *** Draft method, for development use, may change without warning *** +-// return internal actor, usefull for the polling if process died ++// send SIGTERM signal to the subprocess, wait for grace period and ++// eventually send SIGKILL ++CZMQ_EXPORT void ++ zproc_shutdown (zproc_t *self, int timeout); ++ ++// *** Draft method, for development use, may change without warning *** ++// return internal actor, useful for the polling if process died + CZMQ_EXPORT void * + zproc_actor (zproc_t *self); + +diff --git a/src/zproc.c b/src/zproc.c +index a65c6e6..305c4a8 100644 +--- a/src/zproc.c ++++ b/src/zproc.c +@@ -95,9 +95,11 @@ struct _zpair_t { + }; + + static zpair_t* +-zpair_new (char* endpoint) { ++zpair_new (char *endpoint) { + zpair_t *self = (zpair_t*) zmalloc (sizeof (zpair_t)); +- self->endpoint = endpoint; ++ if (self) { ++ self->endpoint = endpoint; ++ } + return self; + } + +@@ -213,7 +215,6 @@ struct _zproc_t { + int stdoutpipe [2]; // stdout pipe + int stderrpipe [2]; // stderr pipe + +- zpair_t *execpair; // pair used to synchronize zproc_run with actor + zpair_t *stdinpair; // stdin socketpair + zpair_t *stdoutpair; // stdout socketpair + zpair_t *stderrpair; // stderr socketpair +@@ -237,6 +238,7 @@ zproc_new () + } + + zproc_t *self = (zproc_t*) zmalloc (sizeof (zproc_t)); ++ assert (self); + self->verbose = false; + + self->stdinpipe [0] = -1; +@@ -247,19 +249,19 @@ zproc_new () + self->stderrpipe [1] = -1; + + zuuid_t *uuid = zuuid_new (); +- self->execpair = zpair_new ( +- zsys_sprintf ("#inproc://zproc-%s-exec", zuuid_str_canonical (uuid)) +- ); +- zpair_mkpair (self->execpair); ++ assert (uuid); + self->stdinpair = zpair_new ( + zsys_sprintf ("#inproc://zproc-%s-stdin", zuuid_str_canonical (uuid)) + ); ++ assert (self->stdinpair); + self->stdoutpair = zpair_new ( + zsys_sprintf ("#inproc://zproc-%s-stdout", zuuid_str_canonical (uuid)) + ); ++ assert (self->stdoutpair); + self->stderrpair = zpair_new ( + zsys_sprintf ("#inproc://zproc-%s-stderr", zuuid_str_canonical (uuid)) + ); ++ assert (self->stderrpair); + zuuid_destroy (&uuid); + + return self; +@@ -271,23 +273,16 @@ zproc_destroy (zproc_t **self_p) { + assert (self_p); + if (*self_p) { + zproc_t *self = *self_p; +- zproc_wait (self, true); ++ zproc_shutdown (self, 5000); + zactor_destroy (&self->actor); + +- if (self->stdinpipe [0] != -1) { +- close (self->stdinpipe [0]); +- close (self->stdinpipe [1]); +- } +- if (self->stdoutpipe [0] != -1) { +- close (self->stdoutpipe [0]); +- close (self->stdoutpipe [1]); +- } +- if (self->stderrpipe [0] != -1) { +- close (self->stderrpipe [0]); +- close (self->stderrpipe [1]); +- } ++ if (self->stdinpipe [0] != -1) close (self->stdinpipe [0]); ++ if (self->stdinpipe [1] != -1) close (self->stdinpipe [1]); ++ if (self->stdoutpipe [0] != -1) close (self->stdoutpipe [0]); ++ if (self->stdoutpipe [1] != -1) close (self->stdoutpipe [1]); ++ if (self->stderrpipe [0] != -1) close (self->stderrpipe [0]); ++ if (self->stderrpipe [1] != -1) close (self->stderrpipe [1]); + +- zpair_destroy (&self->execpair); + zpair_destroy (&self->stdinpair); + zpair_destroy (&self->stdoutpair); + zpair_destroy (&self->stderrpair); +@@ -430,7 +425,7 @@ int + zproc_returncode (zproc_t *self) { + assert (self); + assert (zproc_pid(self)); +- zproc_wait (self, false); ++ zproc_wait (self, 0); + return self->return_code; + } + +@@ -456,74 +451,118 @@ s_fd_in_handler (zloop_t *self, zmq_pollitem_t *item, void *socket) + byte buf [BUF_SIZE]; + ssize_t r = 1; + +- while (r > 0) { +- memset (buf, '\0', BUF_SIZE); +- r = read (item->fd, buf, BUF_SIZE); +- if (r == -1) { +- zsys_error ("read from fd %d: %s", item->fd, strerror (errno)); +- break; +- } +- else +- if (r == 0) +- break; +- zframe_t *frame = zframe_new (buf, r); +- zsock_bsend (socket, "f", frame, NULL); +- zframe_destroy (&frame); ++ memset (buf, '\0', BUF_SIZE); ++ r = read (item->fd, buf, BUF_SIZE); ++ if (r == -1) { ++ zsys_warning ("read from fd %d: %s", item->fd, strerror (errno)); ++ return 0; + } ++ else ++ if (r == 0) ++ return 0; ++ zframe_t *frame = zframe_new (buf, r); ++ zsock_bsend (socket, "f", frame, NULL); ++ zframe_destroy (&frame); + return 0; + #undef BUF_SIZE + } + + static int +-s_fd_out_handler (zloop_t *self, zmq_pollitem_t *item, void *socket) ++s_fd_out_handler (zloop_t *self, zsock_t *socket, void *fd_p) + { ++ assert (self); ++ assert (socket); ++ assert (fd_p); + ssize_t r = 1; ++ int fd = *(int*)fd_p; + +- while (r > 0) { +- +- zframe_t *frame; +- r = zsock_brecv (socket, "f", &frame); +- if (r == -1) { +- zsys_error ("read from socket <%p>: %s", socket, strerror (errno)); +- break; +- } +- +- r = write (item->fd, zframe_data (frame), zframe_size (frame)); ++ zframe_t *frame; ++ r = zsock_brecv (socket, "f", &frame); ++ if (r == -1) { + zframe_destroy (&frame); ++ zsys_error ("read from socket <%p>: %s", socket, strerror (errno)); ++ return -1; ++ } + +- if (r == -1) { +- zsys_error ("write to fd %d: %s", item->fd, strerror (errno)); +- break; +- } ++ r = write (fd, zframe_data (frame), zframe_size (frame)); ++ zframe_destroy (&frame); ++ ++ if (r == -1) { ++ zsys_error ("write to fd %d: %s", fd, strerror (errno)); ++ return -1; + } + return 0; + } + ++// connect pipe (fd) with zeromq socket, so when data are signaled on `fd`, they are forwarded to `socket` ++// used for readable ends of pipesm like stdout/stderr + static int +-s_zproc_addfd (zproc_t *self, int fd, void* socket, int flags) { ++s_zproc_readfd (zproc_t *self, int fd, void* socket) { + assert (self); + #if defined (__WINDOWS__) +- zsys_error ("s_zproc_addfd not implemented for Windows"); ++ zsys_error ("s_zproc_readfd not implemented for Windows"); + return -1; + #else +- zmq_pollitem_t it = {NULL, fd, flags, 0}; ++ assert (socket); ++ assert (zsock_is (socket)); ++ zmq_pollitem_t it = {NULL, fd, ZMQ_POLLIN, 0}; + return zloop_poller ( + self->loop_ref, + &it, +- flags == ZMQ_POLLIN ? s_fd_in_handler : s_fd_out_handler, ++ s_fd_in_handler, + socket); + #endif + } + ++// connect zeromq `socket` with writable end of pipe. When data are signaled on `fd`, they are forwarded to `fd` ++// used for writable ends of pipes like stdin ++static int ++s_zproc_readsocket (zproc_t *self, int* fd_p, void* socket) { ++ assert (self); ++#if defined (__WINDOWS__) ++ zsys_error ("s_zproc_readfd not implemented for Windows"); ++ return -1; ++#else ++ assert (socket); ++ assert (zsock_is (socket)); ++ return zloop_reader ( ++ self->loop_ref, ++ (zsock_t*)socket, ++ s_fd_out_handler, ++ (void*)fd_p); ++#endif ++} ++ ++ + static int + s_zproc_alive (zloop_t *loop, int timer_id, void *args) + { + zproc_t *self = (zproc_t*) args; +- if (zsys_interrupted) +- return -1; +- if (zproc_pid (self) && zproc_running (self)) ++ if (! zproc_running (self)) + return 0; +- return -1; ++#if defined (__WINDOWS__) ++ if (zproc_running (self)) ++ return 0; ++#else ++ int status; ++ int r = waitpid (self->pid, &status, WNOHANG); ++ if (r > 0) { ++ if (WIFEXITED(status)) { ++ self->return_code = WEXITSTATUS(status); ++ if (self->verbose) ++ zsys_debug ("zproc_wait [%d]:\tWIFEXITED, self->return_code=%d", self->pid, self->return_code); ++ self->running = false; ++ } ++ else if (WIFSIGNALED(status)) { ++ self->return_code = - WTERMSIG(status); ++ if (self->verbose) ++ zsys_debug ("zproc_wait [%d]:\tWIFSIGNALED, self->return_code=%d", self->pid, self->return_code); ++ self->running = false; ++ } ++ return -1; ++ } ++ return 0; ++#endif + } + + static int +@@ -546,7 +585,6 @@ s_zproc_execve (zproc_t *self) + zsys_debug ("zproc: command to start: %s", commandline); + + siStartInfo.cb = sizeof (siStartInfo); +- zsock_signal (zpair_write (self->execpair), 0); + self->running = CreateProcessA( + NULL, // app name + commandline, // command line +@@ -576,17 +614,20 @@ s_zproc_execve (zproc_t *self) + fcntl (self->stdinpipe [0], F_SETFL, n_flags); + dup2 (self->stdinpipe [0], STDIN_FILENO); + close (self->stdinpipe [1]); ++ self->stdinpipe[1] = -1; + } + + // redirect stdout if set_stdout was called + if (self->stdoutpipe [0] != -1) { + close (self->stdoutpipe [0]); ++ self->stdoutpipe [0] = -1; + dup2 (self->stdoutpipe [1], STDOUT_FILENO); + } + + // redirect stderr if set_stderr was called + if (self->stderrpipe [0] != -1) { + close (self->stderrpipe [0]); ++ self->stderrpipe [0] = -1; + dup2 (self->stderrpipe [1], STDERR_FILENO); + } + +@@ -621,7 +662,6 @@ s_zproc_execve (zproc_t *self) + else + env = environ; + +- zsock_signal (zpair_write (self->execpair), 0); + r = execve (filename, argv2, env); + if (r == -1) { + zsys_error ("fail to run %s: %s", filename, strerror (errno)); +@@ -643,19 +683,22 @@ s_zproc_execve (zproc_t *self) + zsys_debug ("process %s with pid %d started", filename, self->pid); + + if (self->stdinpipe [0] != -1) { +- s_zproc_addfd (self, self->stdinpipe [1], zpair_read (self->stdinpair), ZMQ_POLLOUT); ++ s_zproc_readsocket (self, self->stdinpipe+1, zpair_read (self->stdinpair)); + close (self->stdinpipe [0]); ++ self->stdinpipe [0] = -1; + } + + // add a handler for read end of stdout + if (self->stdoutpipe [1] != -1) { +- s_zproc_addfd (self, self->stdoutpipe [0], zpair_write (self->stdoutpair), ZMQ_POLLIN); ++ s_zproc_readfd (self, self->stdoutpipe [0], zpair_write (self->stdoutpair)); + close (self->stdoutpipe[1]); ++ self->stdoutpipe [1] = -1; + } + // add a handler for read end of stderr + if (self->stderrpipe [1] != -1) { +- s_zproc_addfd (self, self->stderrpipe [0], zpair_write (self->stderrpair), ZMQ_POLLIN); ++ s_zproc_readfd (self, self->stderrpipe [0], zpair_write (self->stderrpair)); + close (self->stderrpipe[1]); ++ self->stderrpipe [1] = -1; + } + } + +@@ -685,7 +728,7 @@ s_pipe_handler (zloop_t *loop, zsock_t *pipe, void *args) { + } + + s_zproc_execve (self); +- zsock_wait (self->execpair); ++ zclock_sleep (10); // magic sleep, give execve a bit of time + zsock_signal (pipe, 0); + } + +@@ -703,6 +746,7 @@ s_zproc_actor (zsock_t *pipe, void *args) + zproc_t *self = (zproc_t*) args; + zloop_t *loop = zloop_new (); + assert (loop); ++ // zloop_set_verbose (loop, self->verbose); + self->loop_ref = loop; + self->pipe = pipe; + +@@ -712,6 +756,10 @@ s_zproc_actor (zsock_t *pipe, void *args) + zsock_signal (pipe, 0); + zloop_start (loop); + zloop_destroy (&loop); ++ while (zproc_running (self)) { ++ zclock_sleep (500); ++ s_zproc_alive (NULL, -1, self); ++ } + zsock_signal (pipe, 0); + } + +@@ -722,7 +770,14 @@ zproc_run (zproc_t *self) + assert (!self->actor); + + if (!self->args || zlist_size (self->args) == 0) { +- zsys_error ("No arguments, nothing to run. Call zproc_set_args before"); ++ if (self->verbose) ++ zsys_error ("zproc: No arguments, nothing to run. Call zproc_set_args before"); ++ return -1; ++ } ++ const char *filename = (const char*) zlist_first (self->args); ++ if (!zfile_exists (filename)) { ++ if (self->verbose) ++ zsys_error ("zproc: '%s' does not exists", filename); + return -1; + } + +@@ -736,7 +791,7 @@ zproc_run (zproc_t *self) + } + + int +-zproc_wait (zproc_t *self, bool wait) { ++zproc_wait (zproc_t *self, int timeout) { + #if defined (__WINDOWS__) + if (!self->running) { + if (self->verbose) +@@ -744,10 +799,10 @@ zproc_wait (zproc_t *self, bool wait) { + return self->return_code; + } + +- uint32_t r = WaitForSingleObject (self->piProcInfo.hProcess, wait ? INFINITE : 0); ++ uint32_t r = WaitForSingleObject (self->piProcInfo.hProcess, timeout == -1 ? INFINITE : timeout); + if (self->verbose) + zsys_debug ("zproc_wait [%d]:\twaitforsingleobject, r=%d", zproc_pid (self), r); +- if (!wait && r == 0x00000102) { ++ if (timeout >= 0 && r == 0x00000102) { + // still running + return self->return_code; + } +@@ -764,13 +819,12 @@ zproc_wait (zproc_t *self, bool wait) { + return -1; + #else + assert (self); ++ + if (!self->pid) + return 0; + + if (self->verbose) +- zsys_debug ("zproc_wait [%d]: wait=%s", self->pid, wait ? "true" : "false"); +- int status = -1; +- int options = !wait ? WNOHANG : 0; ++ zsys_debug ("zproc_wait [%d]: timeout=%d", self->pid, timeout); + if (self->verbose) + zsys_debug ("zproc_wait [%d]:\t!self->running=%s", self->pid, self->running ? "true" : "false"); + if (!self->running) +@@ -778,43 +832,36 @@ zproc_wait (zproc_t *self, bool wait) { + + if (self->verbose) + zsys_debug ("zproc_wait [%d]:\twaitpid", self->pid); +- int r = waitpid (self->pid, &status, options); +- if (self->verbose) +- zsys_debug ("zproc_wait [%d]:\twaitpid, r=%d", self->pid, r); +- if (!wait && r == 0) +- return self->return_code; + +- if (WIFEXITED(status)) { +- self->running = false; +- self->return_code = WEXITSTATUS(status); +- if (self->verbose) +- zsys_debug ("zproc_wait [%d]:\tWIFEXITED, self->return_code=%d", self->pid, self->return_code); ++ if (timeout < 0) { ++ // infinite wait ++ while (zproc_running (self)) ++ zclock_sleep (200); + return self->return_code; + } +- else if (WIFSIGNALED(status)) { +- self->running = false; +- self->return_code = - WTERMSIG(status); +- if (self->verbose) +- zsys_debug ("zproc_wait [%d]:\tWIFSIGNALED, self->return_code=%d", self->pid, self->return_code); ++ else if (timeout == 0) { ++ // just check and continue + return self->return_code; +- +- /* +- if (WCOREDUMP(status)) { +- self->core_dumped = true; ++ } else { ++ // wait up to timeout ++ int quit = zclock_mono () + timeout; ++ while (true) { ++ if (! zproc_running (self)) ++ break; ++ if (zclock_mono () >= quit) ++ break; ++ zclock_sleep (200); + } +- */ ++ return self->return_code; + } +- if (self->verbose) +- zsys_debug ("zproc_wait [%d]: self->return_code=%d", self->pid, self->return_code); +- return ZPROC_RUNNING; + #endif + } + + bool + zproc_running (zproc_t *self) { + assert (self); +- assert (zproc_pid (self)); +- return zproc_wait (self, false) == ZPROC_RUNNING; ++ if (! zproc_pid (self)) return false; ++ return zproc_wait (self, 0) == ZPROC_RUNNING; + } + + void * +@@ -832,17 +879,34 @@ zproc_kill (zproc_t *self, int signum) { + if (signum == SIGTERM) { + if (! TerminateProcess (self->piProcInfo.hProcess, 255)) + zsys_error ("zproc_kill [%d]:\tTerminateProcess failed", zproc_pid (self)); +- zproc_wait (self, false); ++ zproc_wait (self, 0); + } else { + zsys_error ("zproc_kill: [%d]:\tOnly SIGTERM is implemented on windows", zproc_pid (self)); + } + } + #else +- if (zproc_pid (self) > 0) { ++ if (zproc_running (self)) { + int r = kill (self->pid, signum); + if (r != 0) + zsys_error ("kill of pid=%d failed: %s", self->pid, strerror (errno)); +- zproc_wait (self, false); ++ zproc_wait (self, 0); ++ } ++#endif ++} ++ ++// send SIGTERM signal to the subprocess, wait for grace period and KILL ++void ++zproc_shutdown (zproc_t *self, int timeout) ++{ ++ assert (self); ++ if (timeout < 0) timeout = 0; ++ ++ zproc_kill (self, SIGTERM); ++ zproc_wait (self, timeout); ++#if ! defined (__WINDOWS__) ++ if (zproc_running (self)) { ++ zproc_kill (self, SIGKILL); ++ zproc_wait (self, timeout); + } + #endif + } +@@ -960,6 +1024,7 @@ zproc_test (bool verbose) + printf ("OK\n"); + return; + #endif ++ { + // Test case #1: run command, wait until it ends and get the (stdandard) output + zproc_t *self = zproc_new (); + assert (self); +@@ -986,15 +1051,103 @@ zproc_test (bool verbose) + if (verbose) + zframe_print (frame, "1:"); + zframe_destroy (&frame); +- r = zproc_wait (self, true); ++ r = zproc_wait (self, -1); + assert (r == 0); + zproc_destroy (&self); ++ } + +- // Test case #2: use never ending subprocess and poller to read data from it +- // Create new zproc instance +- self = zproc_new (); ++ { ++ // Test case#2: run zsp helper with a content written on stdin, check if it was passed to stdout ++ zproc_t *self = zproc_new (); ++ assert (self); ++ zproc_set_verbose (self, verbose); ++ // forward input from stdin to stderr ++ zproc_set_argsx (self, file, "--stdin", "--stderr", NULL); ++ // FIXME: there is a BUG in zproc somewhere, you can't gen an output from both stdout/stderr ++ //zproc_set_argsx (self, file, "--stdin", "--stdout", "--stderr", NULL); ++ zproc_set_stdin (self, NULL); ++ // FIXME: the bug ++ //zproc_set_stdout (self, NULL); ++ zproc_set_stderr (self, NULL); ++ ++ // send data to stdin ++ int r = zproc_run (self); ++ assert (r == 0); ++ zframe_t *frame = zframe_new ("Lorem ipsum\0\0", strlen ("Lorem ipsum")+2); ++ assert (frame); ++ zsock_bsend (zproc_stdin (self), "f", frame); ++ zframe_destroy (&frame); ++ ++ // FIXME: the bug ++ //zproc_set_stdout (self, NULL); ++ // read data from stdout ++ /* ++ zsys_debug ("BAF1"); ++ zsock_brecv (zproc_stdout (self), "f", &frame); ++ zsys_debug ("BAF2"); ++ assert (frame); ++ assert (zframe_data (frame)); ++ if (verbose) ++ zframe_print (frame, "2.stdout:"); ++ assert (!strncmp ((char*) zframe_data (frame), "Lorem ipsum", 11)); ++ */ ++ ++ // read data from stderr ++ zsock_brecv (zproc_stderr (self), "f", &frame); ++ assert (frame); ++ assert (zframe_data (frame)); ++ if (verbose) ++ zframe_print (frame, "2.stderr:"); ++ assert (!strncmp ((char*) zframe_data (frame), "Lorem ipsum", 11)); ++ zproc_kill (self, SIGTERM); ++ zproc_wait (self, -1); ++ zframe_destroy (&frame); ++ zproc_destroy (&self); ++ } ++ ++ { ++ // Test case#3: run non existing binary ++ zproc_t *self = zproc_new (); ++ assert (self); + zproc_set_verbose (self, verbose); ++ // forward input from stdin to stderr ++ zproc_set_argsx (self, "/not/existing/file", NULL); ++ ++ int r = zproc_run (self); ++ assert (r == -1); ++ zproc_destroy (&self); ++ } ++ ++ { ++ // Test case #4: child abort itself ++ zproc_t *self = zproc_new (); + assert (self); ++ zproc_set_verbose (self, verbose); ++ zproc_set_argsx (self, file, "--verbose", "--abrt", NULL); ++ zproc_set_stdout (self, NULL); ++ zproc_set_stderr (self, NULL); ++ zproc_set_stdin (self, NULL); ++ ++ int r = zproc_run (self); ++ zclock_sleep (100); // to let actor start the process ++ assert (r != -1); ++ zclock_sleep (100); ++ zframe_t *frame; ++ zsock_brecv (zproc_stdout (self), "f", &frame); ++ assert (zframe_is (frame)); ++ assert (zframe_size (frame) > 0); ++ zframe_destroy (&frame); ++ zproc_wait (self, -1); ++ assert (zproc_returncode (self) == -SIGABRT); ++ zproc_destroy (&self); ++ } ++ ++ { ++ // Test case #5: use never ending subprocess and poller to read data from it ++ // Create new zproc instance ++ zproc_t *self = zproc_new (); ++ assert (self); ++ zproc_set_verbose (self, verbose); + // join stdout of the process to zeromq socket + // all data will be readable from zproc_stdout socket + zproc_set_stdout (self, NULL); +@@ -1025,7 +1178,7 @@ zproc_test (bool verbose) + zsys_debug("zproc_test() : sleeping 4000 msec to gather some output from helper"); + zclock_sleep (4000); + zproc_kill (self, SIGTERM); +- zproc_wait (self, true); ++ zproc_wait (self, -1); + + // read the content from zproc_stdout - use zpoller and a loop + bool stdout_read = false; +@@ -1089,6 +1242,47 @@ zproc_test (bool verbose) + assert (stdout_read); + zpoller_destroy (&poller); + zproc_destroy (&self); ++ } ++ { ++ // testcase #6 wait for process that hangs, kill it ++ zproc_t *self = zproc_new (); ++ assert (self); ++ zproc_set_verbose (self, verbose); ++ ++ zproc_set_argsx (self, file, NULL); ++ ++ if (verbose) ++ zsys_debug("zproc_test() : launching helper '%s'", file); ++ ++ int r = zproc_run (self); ++ assert (r == 0); ++ r = zproc_wait (self, 1000); ++ assert (r == ZPROC_RUNNING); ++ assert (zproc_running (self)); ++ zproc_shutdown (self, 1000); ++ assert (!zproc_running (self)); ++ zproc_destroy (&self); ++ } ++ { ++ // testcase #7 wait for process that exits earlier ++ zproc_t *self = zproc_new (); ++ assert (self); ++ zproc_set_verbose (self, verbose); ++ ++ zproc_set_argsx (self, file, "--quit", "1", NULL); ++ ++ if (verbose) ++ zsys_debug("zproc_test() : launching helper '%s' --quit 1", file); ++ ++ int r = zproc_run (self); ++ assert (r == 0); ++ int t = zclock_mono (); ++ r = zproc_wait (self, 8000); ++ assert (r == 0); ++ t = zclock_mono () - t; ++ assert (t < 2000); ++ zproc_destroy (&self); ++ } + // @end + + // to have zpair print and arr print methods +diff --git a/src/zsp.c b/src/zsp.c +index 67a499f..ba57beb 100644 +--- a/src/zsp.c ++++ b/src/zsp.c +@@ -29,6 +29,8 @@ int main (int argc, char *argv []) + bool use_stdin = false; + bool use_stderr = false; + bool use_stdout = false; ++ bool abrt = false; ++ int quit = 0; + + char *message = NULL; + +@@ -41,7 +43,9 @@ int main (int argc, char *argv []) + #endif + puts (" --stderr / -e output on stderr"); + puts (" --stdout / -o output on stdout"); ++ puts (" --abrt / -a crash with SIGABRT on start"); + puts (" --verbose / -v verbose mode"); ++ puts (" --quit / -q X quit after X seconds"); + puts (" --help / -h this information"); + return 0; + } +@@ -62,6 +66,16 @@ int main (int argc, char *argv []) + || streq (argv [argn], "-v")) + verbose = true; + else ++ if (streq (argv [argn], "--abrt") ++ || streq (argv [argn], "-a")) ++ abrt = true; ++ else ++ if (streq (argv [argn], "--quit") ++ || streq (argv [argn], "-q")) { ++ quit = atoi (argv [argn + 1]) * 1000; ++ ++argn; ++ } ++ else + if (argv [argn][0] == '-') { + printf ("Unknown option: %s\n", argv [argn]); + return 1; +@@ -87,7 +101,18 @@ int main (int argc, char *argv []) + assert (r == 0); + } + ++ if (abrt) { ++ if (verbose) ++ zsys_info ("Going to abort myself"); ++#if defined (__WINDOWS__) ++ assert (false); // TODO: how to do kill myelf on Windows? ++#else ++ kill (getpid (), SIGABRT); ++#endif ++ } ++ + // Insert main code here ++ int64_t start = zclock_mono (); + while (!zsys_interrupted) { + #if ! defined (__WINDOWS__) + if (use_stdin) { +@@ -110,6 +135,7 @@ int main (int argc, char *argv []) + fprintf (stdout, "%s\n", message); + + zclock_sleep (50); ++ if (quit && zclock_mono () - start > quit) break; + } + + zfile_destroy (&stdinf); |