Merge branch 'ab/config-based-hooks-base' into seen
[git] / t / helper / test-simple-ipc.c
1 /*
2  * test-simple-ipc.c: verify that the Inter-Process Communication works.
3  */
4
5 #include "test-tool.h"
6 #include "cache.h"
7 #include "strbuf.h"
8 #include "simple-ipc.h"
9 #include "parse-options.h"
10 #include "thread-utils.h"
11 #include "strvec.h"
12
13 #ifndef SUPPORTS_SIMPLE_IPC
14 int cmd__simple_ipc(int argc, const char **argv)
15 {
16         die("simple IPC not available on this platform");
17 }
18 #else
19
20 /*
21  * The test daemon defines an "application callback" that supports a
22  * series of commands (see `test_app_cb()`).
23  *
24  * Unknown commands are caught here and we send an error message back
25  * to the client process.
26  */
27 static int app__unhandled_command(const char *command,
28                                   ipc_server_reply_cb *reply_cb,
29                                   struct ipc_server_reply_data *reply_data)
30 {
31         struct strbuf buf = STRBUF_INIT;
32         int ret;
33
34         strbuf_addf(&buf, "unhandled command: %s", command);
35         ret = reply_cb(reply_data, buf.buf, buf.len);
36         strbuf_release(&buf);
37
38         return ret;
39 }
40
41 /*
42  * Reply with a single very large buffer.  This is to ensure that
43  * long response are properly handled -- whether the chunking occurs
44  * in the kernel or in the (probably pkt-line) layer.
45  */
46 #define BIG_ROWS (10000)
47 static int app__big_command(ipc_server_reply_cb *reply_cb,
48                             struct ipc_server_reply_data *reply_data)
49 {
50         struct strbuf buf = STRBUF_INIT;
51         int row;
52         int ret;
53
54         for (row = 0; row < BIG_ROWS; row++)
55                 strbuf_addf(&buf, "big: %.75d\n", row);
56
57         ret = reply_cb(reply_data, buf.buf, buf.len);
58         strbuf_release(&buf);
59
60         return ret;
61 }
62
63 /*
64  * Reply with a series of lines.  This is to ensure that we can incrementally
65  * compute the response and chunk it to the client.
66  */
67 #define CHUNK_ROWS (10000)
68 static int app__chunk_command(ipc_server_reply_cb *reply_cb,
69                               struct ipc_server_reply_data *reply_data)
70 {
71         struct strbuf buf = STRBUF_INIT;
72         int row;
73         int ret;
74
75         for (row = 0; row < CHUNK_ROWS; row++) {
76                 strbuf_setlen(&buf, 0);
77                 strbuf_addf(&buf, "big: %.75d\n", row);
78                 ret = reply_cb(reply_data, buf.buf, buf.len);
79         }
80
81         strbuf_release(&buf);
82
83         return ret;
84 }
85
86 /*
87  * Slowly reply with a series of lines.  This is to model an expensive to
88  * compute chunked response (which might happen if this callback is running
89  * in a thread and is fighting for a lock with other threads).
90  */
91 #define SLOW_ROWS     (1000)
92 #define SLOW_DELAY_MS (10)
93 static int app__slow_command(ipc_server_reply_cb *reply_cb,
94                              struct ipc_server_reply_data *reply_data)
95 {
96         struct strbuf buf = STRBUF_INIT;
97         int row;
98         int ret;
99
100         for (row = 0; row < SLOW_ROWS; row++) {
101                 strbuf_setlen(&buf, 0);
102                 strbuf_addf(&buf, "big: %.75d\n", row);
103                 ret = reply_cb(reply_data, buf.buf, buf.len);
104                 sleep_millisec(SLOW_DELAY_MS);
105         }
106
107         strbuf_release(&buf);
108
109         return ret;
110 }
111
112 /*
113  * The client sent a command followed by a (possibly very) large buffer.
114  */
115 static int app__sendbytes_command(const char *received, size_t received_len,
116                                   ipc_server_reply_cb *reply_cb,
117                                   struct ipc_server_reply_data *reply_data)
118 {
119         struct strbuf buf_resp = STRBUF_INIT;
120         const char *p = "?";
121         int len_ballast = 0;
122         int k;
123         int errs = 0;
124         int ret;
125
126         /*
127          * The test is setup to send:
128          *     "sendbytes" SP <n * char>
129          */
130         if (received_len < strlen("sendbytes "))
131                 BUG("received_len is short in app__sendbytes_command");
132
133         if (skip_prefix(received, "sendbytes ", &p))
134                 len_ballast = strlen(p);
135
136         /*
137          * Verify that the ballast is n copies of a single letter.
138          * And that the multi-threaded IO layer didn't cross the streams.
139          */
140         for (k = 1; k < len_ballast; k++)
141                 if (p[k] != p[0])
142                         errs++;
143
144         if (errs)
145                 strbuf_addf(&buf_resp, "errs:%d\n", errs);
146         else
147                 strbuf_addf(&buf_resp, "rcvd:%c%08d\n", p[0], len_ballast);
148
149         ret = reply_cb(reply_data, buf_resp.buf, buf_resp.len);
150
151         strbuf_release(&buf_resp);
152
153         return ret;
154 }
155
156 /*
157  * An arbitrary fixed address to verify that the application instance
158  * data is handled properly.
159  */
160 static int my_app_data = 42;
161
162 static ipc_server_application_cb test_app_cb;
163
164 /*
165  * This is the "application callback" that sits on top of the
166  * "ipc-server".  It completely defines the set of commands supported
167  * by this application.
168  */
169 static int test_app_cb(void *application_data,
170                        const char *command, size_t command_len,
171                        ipc_server_reply_cb *reply_cb,
172                        struct ipc_server_reply_data *reply_data)
173 {
174         /*
175          * Verify that we received the application-data that we passed
176          * when we started the ipc-server.  (We have several layers of
177          * callbacks calling callbacks and it's easy to get things mixed
178          * up (especially when some are "void*").)
179          */
180         if (application_data != (void*)&my_app_data)
181                 BUG("application_cb: application_data pointer wrong");
182
183         if (command_len == 4 && !strncmp(command, "quit", 4)) {
184                 /*
185                  * The client sent a "quit" command.  This is an async
186                  * request for the server to shutdown.
187                  *
188                  * We DO NOT send the client a response message
189                  * (because we have nothing to say and the other
190                  * server threads have not yet stopped).
191                  *
192                  * Tell the ipc-server layer to start shutting down.
193                  * This includes: stop listening for new connections
194                  * on the socket/pipe and telling all worker threads
195                  * to finish/drain their outgoing responses to other
196                  * clients.
197                  *
198                  * This DOES NOT force an immediate sync shutdown.
199                  */
200                 return SIMPLE_IPC_QUIT;
201         }
202
203         if (command_len == 4 && !strncmp(command, "ping", 4)) {
204                 const char *answer = "pong";
205                 return reply_cb(reply_data, answer, strlen(answer));
206         }
207
208         if (command_len == 3 && !strncmp(command, "big", 3))
209                 return app__big_command(reply_cb, reply_data);
210
211         if (command_len == 5 && !strncmp(command, "chunk", 5))
212                 return app__chunk_command(reply_cb, reply_data);
213
214         if (command_len == 4 && !strncmp(command, "slow", 4))
215                 return app__slow_command(reply_cb, reply_data);
216
217         if (command_len >= 10 && starts_with(command, "sendbytes "))
218                 return app__sendbytes_command(command, command_len,
219                                               reply_cb, reply_data);
220
221         return app__unhandled_command(command, reply_cb, reply_data);
222 }
223
224 struct cl_args
225 {
226         const char *subcommand;
227         const char *path;
228         const char *token;
229
230         int nr_threads;
231         int max_wait_sec;
232         int bytecount;
233         int batchsize;
234
235         char bytevalue;
236 };
237
238 static struct cl_args cl_args = {
239         .subcommand = NULL,
240         .path = "ipc-test",
241         .token = NULL,
242
243         .nr_threads = 5,
244         .max_wait_sec = 60,
245         .bytecount = 1024,
246         .batchsize = 10,
247
248         .bytevalue = 'x',
249 };
250
251 /*
252  * This process will run as a simple-ipc server and listen for IPC commands
253  * from client processes.
254  */
255 static int daemon__run_server(void)
256 {
257         int ret;
258
259         struct ipc_server_opts opts = {
260                 .nr_threads = cl_args.nr_threads,
261         };
262
263         /*
264          * Synchronously run the ipc-server.  We don't need any application
265          * instance data, so pass an arbitrary pointer (that we'll later
266          * verify made the round trip).
267          */
268         ret = ipc_server_run(cl_args.path, &opts, test_app_cb, (void*)&my_app_data);
269         if (ret == -2)
270                 error(_("socket/pipe already in use: '%s'"), cl_args.path);
271         else if (ret == -1)
272                 error_errno(_("could not start server on: '%s'"), cl_args.path);
273
274         return ret;
275 }
276
277 #ifndef GIT_WINDOWS_NATIVE
278 /*
279  * This is adapted from `daemonize()`.  Use `fork()` to directly create and
280  * run the daemon in a child process.
281  */
282 static int spawn_server(pid_t *pid)
283 {
284         struct ipc_server_opts opts = {
285                 .nr_threads = cl_args.nr_threads,
286         };
287
288         *pid = fork();
289
290         switch (*pid) {
291         case 0:
292                 if (setsid() == -1)
293                         error_errno(_("setsid failed"));
294                 close(0);
295                 close(1);
296                 close(2);
297                 sanitize_stdfds();
298
299                 return ipc_server_run(cl_args.path, &opts, test_app_cb,
300                                       (void*)&my_app_data);
301
302         case -1:
303                 return error_errno(_("could not spawn daemon in the background"));
304
305         default:
306                 return 0;
307         }
308 }
309 #else
310 /*
311  * Conceptually like `daemonize()` but different because Windows does not
312  * have `fork(2)`.  Spawn a normal Windows child process but without the
313  * limitations of `start_command()` and `finish_command()`.
314  */
315 static int spawn_server(pid_t *pid)
316 {
317         char test_tool_exe[MAX_PATH];
318         struct strvec args = STRVEC_INIT;
319         int in, out;
320
321         GetModuleFileNameA(NULL, test_tool_exe, MAX_PATH);
322
323         in = open("/dev/null", O_RDONLY);
324         out = open("/dev/null", O_WRONLY);
325
326         strvec_push(&args, test_tool_exe);
327         strvec_push(&args, "simple-ipc");
328         strvec_push(&args, "run-daemon");
329         strvec_pushf(&args, "--name=%s", cl_args.path);
330         strvec_pushf(&args, "--threads=%d", cl_args.nr_threads);
331
332         *pid = mingw_spawnvpe(args.v[0], args.v, NULL, NULL, in, out, out);
333         close(in);
334         close(out);
335
336         strvec_clear(&args);
337
338         if (*pid < 0)
339                 return error(_("could not spawn daemon in the background"));
340
341         return 0;
342 }
343 #endif
344
345 /*
346  * This is adapted from `wait_or_whine()`.  Watch the child process and
347  * let it get started and begin listening for requests on the socket
348  * before reporting our success.
349  */
350 static int wait_for_server_startup(pid_t pid_child)
351 {
352         int status;
353         pid_t pid_seen;
354         enum ipc_active_state s;
355         time_t time_limit, now;
356
357         time(&time_limit);
358         time_limit += cl_args.max_wait_sec;
359
360         for (;;) {
361                 pid_seen = waitpid(pid_child, &status, WNOHANG);
362
363                 if (pid_seen == -1)
364                         return error_errno(_("waitpid failed"));
365
366                 else if (pid_seen == 0) {
367                         /*
368                          * The child is still running (this should be
369                          * the normal case).  Try to connect to it on
370                          * the socket and see if it is ready for
371                          * business.
372                          *
373                          * If there is another daemon already running,
374                          * our child will fail to start (possibly
375                          * after a timeout on the lock), but we don't
376                          * care (who responds) if the socket is live.
377                          */
378                         s = ipc_get_active_state(cl_args.path);
379                         if (s == IPC_STATE__LISTENING)
380                                 return 0;
381
382                         time(&now);
383                         if (now > time_limit)
384                                 return error(_("daemon not online yet"));
385
386                         continue;
387                 }
388
389                 else if (pid_seen == pid_child) {
390                         /*
391                          * The new child daemon process shutdown while
392                          * it was starting up, so it is not listening
393                          * on the socket.
394                          *
395                          * Try to ping the socket in the odd chance
396                          * that another daemon started (or was already
397                          * running) while our child was starting.
398                          *
399                          * Again, we don't care who services the socket.
400                          */
401                         s = ipc_get_active_state(cl_args.path);
402                         if (s == IPC_STATE__LISTENING)
403                                 return 0;
404
405                         /*
406                          * We don't care about the WEXITSTATUS() nor
407                          * any of the WIF*(status) values because
408                          * `cmd__simple_ipc()` does the `!!result`
409                          * trick on all function return values.
410                          *
411                          * So it is sufficient to just report the
412                          * early shutdown as an error.
413                          */
414                         return error(_("daemon failed to start"));
415                 }
416
417                 else
418                         return error(_("waitpid is confused"));
419         }
420 }
421
422 /*
423  * This process will start a simple-ipc server in a background process and
424  * wait for it to become ready.  This is like `daemonize()` but gives us
425  * more control and better error reporting (and makes it easier to write
426  * unit tests).
427  */
428 static int daemon__start_server(void)
429 {
430         pid_t pid_child;
431         int ret;
432
433         /*
434          * Run the actual daemon in a background process.
435          */
436         ret = spawn_server(&pid_child);
437         if (pid_child <= 0)
438                 return ret;
439
440         /*
441          * Let the parent wait for the child process to get started
442          * and begin listening for requests on the socket.
443          */
444         ret = wait_for_server_startup(pid_child);
445
446         return ret;
447 }
448
449 /*
450  * This process will run a quick probe to see if a simple-ipc server
451  * is active on this path.
452  *
453  * Returns 0 if the server is alive.
454  */
455 static int client__probe_server(void)
456 {
457         enum ipc_active_state s;
458
459         s = ipc_get_active_state(cl_args.path);
460         switch (s) {
461         case IPC_STATE__LISTENING:
462                 return 0;
463
464         case IPC_STATE__NOT_LISTENING:
465                 return error("no server listening at '%s'", cl_args.path);
466
467         case IPC_STATE__PATH_NOT_FOUND:
468                 return error("path not found '%s'", cl_args.path);
469
470         case IPC_STATE__INVALID_PATH:
471                 return error("invalid pipe/socket name '%s'", cl_args.path);
472
473         case IPC_STATE__OTHER_ERROR:
474         default:
475                 return error("other error for '%s'", cl_args.path);
476         }
477 }
478
479 /*
480  * Send an IPC command token to an already-running server daemon and
481  * print the response.
482  *
483  * This is a simple 1 word command/token that `test_app_cb()` (in the
484  * daemon process) will understand.
485  */
486 static int client__send_ipc(void)
487 {
488         const char *command = "(no-command)";
489         struct strbuf buf = STRBUF_INIT;
490         struct ipc_client_connect_options options
491                 = IPC_CLIENT_CONNECT_OPTIONS_INIT;
492
493         if (cl_args.token && *cl_args.token)
494                 command = cl_args.token;
495
496         options.wait_if_busy = 1;
497         options.wait_if_not_found = 0;
498
499         if (!ipc_client_send_command(cl_args.path, &options,
500                                      command, strlen(command),
501                                      &buf)) {
502                 if (buf.len) {
503                         printf("%s\n", buf.buf);
504                         fflush(stdout);
505                 }
506                 strbuf_release(&buf);
507
508                 return 0;
509         }
510
511         return error("failed to send '%s' to '%s'", command, cl_args.path);
512 }
513
514 /*
515  * Send an IPC command to an already-running server and ask it to
516  * shutdown.  "send quit" is an async request and queues a shutdown
517  * event in the server, so we spin and wait here for it to actually
518  * shutdown to make the unit tests a little easier to write.
519  */
520 static int client__stop_server(void)
521 {
522         int ret;
523         time_t time_limit, now;
524         enum ipc_active_state s;
525
526         time(&time_limit);
527         time_limit += cl_args.max_wait_sec;
528
529         cl_args.token = "quit";
530
531         ret = client__send_ipc();
532         if (ret)
533                 return ret;
534
535         for (;;) {
536                 sleep_millisec(100);
537
538                 s = ipc_get_active_state(cl_args.path);
539
540                 if (s != IPC_STATE__LISTENING) {
541                         /*
542                          * The socket/pipe is gone and/or has stopped
543                          * responding.  Lets assume that the daemon
544                          * process has exited too.
545                          */
546                         return 0;
547                 }
548
549                 time(&now);
550                 if (now > time_limit)
551                         return error(_("daemon has not shutdown yet"));
552         }
553 }
554
555 /*
556  * Send an IPC command followed by ballast to confirm that a large
557  * message can be sent and that the kernel or pkt-line layers will
558  * properly chunk it and that the daemon receives the entire message.
559  */
560 static int do_sendbytes(int bytecount, char byte, const char *path,
561                         const struct ipc_client_connect_options *options)
562 {
563         struct strbuf buf_send = STRBUF_INIT;
564         struct strbuf buf_resp = STRBUF_INIT;
565
566         strbuf_addstr(&buf_send, "sendbytes ");
567         strbuf_addchars(&buf_send, byte, bytecount);
568
569         if (!ipc_client_send_command(path, options,
570                                      buf_send.buf, buf_send.len,
571                                      &buf_resp)) {
572                 strbuf_rtrim(&buf_resp);
573                 printf("sent:%c%08d %s\n", byte, bytecount, buf_resp.buf);
574                 fflush(stdout);
575                 strbuf_release(&buf_send);
576                 strbuf_release(&buf_resp);
577
578                 return 0;
579         }
580
581         return error("client failed to sendbytes(%d, '%c') to '%s'",
582                      bytecount, byte, path);
583 }
584
585 /*
586  * Send an IPC command with ballast to an already-running server daemon.
587  */
588 static int client__sendbytes(void)
589 {
590         struct ipc_client_connect_options options
591                 = IPC_CLIENT_CONNECT_OPTIONS_INIT;
592
593         options.wait_if_busy = 1;
594         options.wait_if_not_found = 0;
595         options.uds_disallow_chdir = 0;
596
597         return do_sendbytes(cl_args.bytecount, cl_args.bytevalue, cl_args.path,
598                             &options);
599 }
600
601 struct multiple_thread_data {
602         pthread_t pthread_id;
603         struct multiple_thread_data *next;
604         const char *path;
605         int bytecount;
606         int batchsize;
607         int sum_errors;
608         int sum_good;
609         char letter;
610 };
611
612 static void *multiple_thread_proc(void *_multiple_thread_data)
613 {
614         struct multiple_thread_data *d = _multiple_thread_data;
615         int k;
616         struct ipc_client_connect_options options
617                 = IPC_CLIENT_CONNECT_OPTIONS_INIT;
618
619         options.wait_if_busy = 1;
620         options.wait_if_not_found = 0;
621         /*
622          * A multi-threaded client should not be randomly calling chdir().
623          * The test will pass without this restriction because the test is
624          * not otherwise accessing the filesystem, but it makes us honest.
625          */
626         options.uds_disallow_chdir = 1;
627
628         trace2_thread_start("multiple");
629
630         for (k = 0; k < d->batchsize; k++) {
631                 if (do_sendbytes(d->bytecount + k, d->letter, d->path, &options))
632                         d->sum_errors++;
633                 else
634                         d->sum_good++;
635         }
636
637         trace2_thread_exit();
638         return NULL;
639 }
640
641 /*
642  * Start a client-side thread pool.  Each thread sends a series of
643  * IPC requests.  Each request is on a new connection to the server.
644  */
645 static int client__multiple(void)
646 {
647         struct multiple_thread_data *list = NULL;
648         int k;
649         int sum_join_errors = 0;
650         int sum_thread_errors = 0;
651         int sum_good = 0;
652
653         for (k = 0; k < cl_args.nr_threads; k++) {
654                 struct multiple_thread_data *d = xcalloc(1, sizeof(*d));
655                 d->next = list;
656                 d->path = cl_args.path;
657                 d->bytecount = cl_args.bytecount + cl_args.batchsize*(k/26);
658                 d->batchsize = cl_args.batchsize;
659                 d->sum_errors = 0;
660                 d->sum_good = 0;
661                 d->letter = 'A' + (k % 26);
662
663                 if (pthread_create(&d->pthread_id, NULL, multiple_thread_proc, d)) {
664                         warning("failed to create thread[%d] skipping remainder", k);
665                         free(d);
666                         break;
667                 }
668
669                 list = d;
670         }
671
672         while (list) {
673                 struct multiple_thread_data *d = list;
674
675                 if (pthread_join(d->pthread_id, NULL))
676                         sum_join_errors++;
677
678                 sum_thread_errors += d->sum_errors;
679                 sum_good += d->sum_good;
680
681                 list = d->next;
682                 free(d);
683         }
684
685         printf("client (good %d) (join %d), (errors %d)\n",
686                sum_good, sum_join_errors, sum_thread_errors);
687
688         return (sum_join_errors + sum_thread_errors) ? 1 : 0;
689 }
690
691 int cmd__simple_ipc(int argc, const char **argv)
692 {
693         const char * const simple_ipc_usage[] = {
694                 N_("test-helper simple-ipc is-active    [<name>] [<options>]"),
695                 N_("test-helper simple-ipc run-daemon   [<name>] [<threads>]"),
696                 N_("test-helper simple-ipc start-daemon [<name>] [<threads>] [<max-wait>]"),
697                 N_("test-helper simple-ipc stop-daemon  [<name>] [<max-wait>]"),
698                 N_("test-helper simple-ipc send         [<name>] [<token>]"),
699                 N_("test-helper simple-ipc sendbytes    [<name>] [<bytecount>] [<byte>]"),
700                 N_("test-helper simple-ipc multiple     [<name>] [<threads>] [<bytecount>] [<batchsize>]"),
701                 NULL
702         };
703
704         const char *bytevalue = NULL;
705
706         struct option options[] = {
707 #ifndef GIT_WINDOWS_NATIVE
708                 OPT_STRING(0, "name", &cl_args.path, N_("name"), N_("name or pathname of unix domain socket")),
709 #else
710                 OPT_STRING(0, "name", &cl_args.path, N_("name"), N_("named-pipe name")),
711 #endif
712                 OPT_INTEGER(0, "threads", &cl_args.nr_threads, N_("number of threads in server thread pool")),
713                 OPT_INTEGER(0, "max-wait", &cl_args.max_wait_sec, N_("seconds to wait for daemon to start or stop")),
714
715                 OPT_INTEGER(0, "bytecount", &cl_args.bytecount, N_("number of bytes")),
716                 OPT_INTEGER(0, "batchsize", &cl_args.batchsize, N_("number of requests per thread")),
717
718                 OPT_STRING(0, "byte", &bytevalue, N_("byte"), N_("ballast character")),
719                 OPT_STRING(0, "token", &cl_args.token, N_("token"), N_("command token to send to the server")),
720
721                 OPT_END()
722         };
723
724         if (argc < 2)
725                 usage_with_options(simple_ipc_usage, options);
726
727         if (argc == 2 && !strcmp(argv[1], "-h"))
728                 usage_with_options(simple_ipc_usage, options);
729
730         if (argc == 2 && !strcmp(argv[1], "SUPPORTS_SIMPLE_IPC"))
731                 return 0;
732
733         cl_args.subcommand = argv[1];
734
735         argc--;
736         argv++;
737
738         argc = parse_options(argc, argv, NULL, options, simple_ipc_usage, 0);
739
740         if (cl_args.nr_threads < 1)
741                 cl_args.nr_threads = 1;
742         if (cl_args.max_wait_sec < 0)
743                 cl_args.max_wait_sec = 0;
744         if (cl_args.bytecount < 1)
745                 cl_args.bytecount = 1;
746         if (cl_args.batchsize < 1)
747                 cl_args.batchsize = 1;
748
749         if (bytevalue && *bytevalue)
750                 cl_args.bytevalue = bytevalue[0];
751
752         /*
753          * Use '!!' on all dispatch functions to map from `error()` style
754          * (returns -1) style to `test_must_fail` style (expects 1).  This
755          * makes shell error messages less confusing.
756          */
757
758         if (!strcmp(cl_args.subcommand, "is-active"))
759                 return !!client__probe_server();
760
761         if (!strcmp(cl_args.subcommand, "run-daemon"))
762                 return !!daemon__run_server();
763
764         if (!strcmp(cl_args.subcommand, "start-daemon"))
765                 return !!daemon__start_server();
766
767         /*
768          * Client commands follow.  Ensure a server is running before
769          * sending any data.  This might be overkill, but then again
770          * this is a test harness.
771          */
772
773         if (!strcmp(cl_args.subcommand, "stop-daemon")) {
774                 if (client__probe_server())
775                         return 1;
776                 return !!client__stop_server();
777         }
778
779         if (!strcmp(cl_args.subcommand, "send")) {
780                 if (client__probe_server())
781                         return 1;
782                 return !!client__send_ipc();
783         }
784
785         if (!strcmp(cl_args.subcommand, "sendbytes")) {
786                 if (client__probe_server())
787                         return 1;
788                 return !!client__sendbytes();
789         }
790
791         if (!strcmp(cl_args.subcommand, "multiple")) {
792                 if (client__probe_server())
793                         return 1;
794                 return !!client__multiple();
795         }
796
797         die("Unhandled subcommand: '%s'", cl_args.subcommand);
798 }
799 #endif