~ Check we can run them, and check their versions */
| 439 | |
| 440 | /*~ Check we can run them, and check their versions */ |
| 441 | void test_subdaemons(const struct lightningd *ld) |
| 442 | { |
| 443 | size_t i; |
| 444 | |
| 445 | /*~ CCAN's ARRAY_SIZE() should always be used on defined arrays like |
| 446 | * the subdaemons array above. You can calculate the number of |
| 447 | * elements it has using `sizeof(subdaemons)/sizeof(subdaemons[0])` |
| 448 | * but if `subdaemons` were refactored into a pointer (eg. to make |
| 449 | * it a dynamic array) that would erroneously evaluate to `1`. |
| 450 | * |
| 451 | * ARRAY_SIZE will cause a compiler error if the argument is actually |
| 452 | * a pointer, not an array. */ |
| 453 | for (i = 0; i < ARRAY_SIZE(subdaemons); i++) { |
| 454 | /*~ CCAN's path module uses tal, so wants a context to |
| 455 | * allocate from. We have a magic convenience context |
| 456 | * `tmpctx` for temporary allocations like this. |
| 457 | * |
| 458 | * Because all our daemons at their core are of form `while |
| 459 | * (!stopped) handle_events();` (an event loop pattern), we |
| 460 | * can free `tmpctx` in that top-level loop after each event |
| 461 | * is handled. |
| 462 | */ |
| 463 | int outfd; |
| 464 | const char *dpath = subdaemon_path(tmpctx, ld, subdaemons[i]); |
| 465 | const char *verstring; |
| 466 | /*~ CCAN's pipecmd module is like popen for grownups: it |
| 467 | * takes pointers to fill in stdin, stdout and stderr file |
| 468 | * descriptors if desired, and the remainder of arguments |
| 469 | * are the command and its argument. */ |
| 470 | pid_t pid = pipecmd(NULL, &outfd, &outfd, |
| 471 | dpath, "--version", NULL); |
| 472 | |
| 473 | /*~ Our logging system: spam goes in at log_debug level, but |
| 474 | * logging is mainly added by developer necessity and removed |
| 475 | * by developer/user complaints. The only strong convention |
| 476 | * is that log_broken() is used for "should never happen". |
| 477 | * |
| 478 | * Note, however, that logging takes care to preserve the |
| 479 | * global `errno` which is set above. */ |
| 480 | log_debug(ld->log, "testing %s", dpath); |
| 481 | |
| 482 | /*~ ccan/err is a wrapper around BSD's err.h, which defines |
| 483 | * the convenience functions err() (error with message |
| 484 | * followed by a string based on errno) and errx() (same,x |
| 485 | * but no errno string). */ |
| 486 | if (pid == -1) |
| 487 | err(EXITCODE_SUBDAEMON_FAIL, "Could not run %s", dpath); |
| 488 | |
| 489 | /*~ CCAN's grab_file module contains a routine to read into a |
| 490 | * tallocated buffer until EOF (with nul appended!) */ |
| 491 | verstring = grab_fd_str(tmpctx, outfd); |
| 492 | /*~ Like many CCAN modules, it set errno on failure, which |
| 493 | * err (ccan/err, but usually just the BSD <err.h>) prints */ |
| 494 | if (!verstring) |
| 495 | err(1, "Could not get output from %s", dpath); |
| 496 | /*~ strstarts is from CCAN/str. */ |
| 497 | if (!strstarts(verstring, version()) |
| 498 | || verstring[strlen(version())] != '\n') |
no test coverage detected