Returns false if already running */
| 1757 | } |
| 1758 | /* Returns false if already running */ |
| 1759 | static bool gossmap_compact(struct gossmap_manage *gm, bool dev_compact) |
| 1760 | { |
| 1761 | int childin[2], execfail[2], childout[2]; |
| 1762 | int saved_errno; |
| 1763 | |
| 1764 | /* Only one at a time please! */ |
| 1765 | if (gm->compactd) |
| 1766 | return false; |
| 1767 | |
| 1768 | /* This checks contents: we want to make sure compactd sees an |
| 1769 | * up-to-date version. */ |
| 1770 | gossmap_manage_get_gossmap(gm); |
| 1771 | |
| 1772 | gm->compactd = tal(gm, struct compactd); |
| 1773 | for (size_t i = 0; i < ARRAY_SIZE(gm->compactd->uuid); i++) |
| 1774 | gm->compactd->uuid[i] = pseudorand(256); |
| 1775 | |
| 1776 | gm->compactd->old_size = gossip_store_len_written(gm->gs); |
| 1777 | status_debug("Executing lightning_gossip_compactd %s %s %s %s", |
| 1778 | GOSSIP_STORE_FILENAME, |
| 1779 | GOSSIP_STORE_COMPACT_FILENAME, |
| 1780 | tal_fmt(tmpctx, "%"PRIu64, gm->compactd->old_size), |
| 1781 | tal_hexstr(tmpctx, gm->compactd->uuid, sizeof(gm->compactd->uuid))); |
| 1782 | |
| 1783 | if (pipe(childin) != 0 || pipe(childout) != 0 || pipe(execfail) != 0) |
| 1784 | status_failed(STATUS_FAIL_INTERNAL_ERROR, |
| 1785 | "Could not create pipes for compactd: %s", |
| 1786 | strerror(errno)); |
| 1787 | |
| 1788 | if (fcntl(execfail[1], F_SETFD, fcntl(execfail[1], F_GETFD) |
| 1789 | | FD_CLOEXEC) < 0) |
| 1790 | status_failed(STATUS_FAIL_INTERNAL_ERROR, |
| 1791 | "Could not set cloexec on compactd fd: %s", |
| 1792 | strerror(errno)); |
| 1793 | |
| 1794 | gm->compactd->pid = fork(); |
| 1795 | if (gm->compactd->pid < 0) |
| 1796 | status_failed(STATUS_FAIL_INTERNAL_ERROR, |
| 1797 | "Could not fork for compactd: %s", |
| 1798 | strerror(errno)); |
| 1799 | |
| 1800 | if (gm->compactd->pid == 0) { |
| 1801 | close(childin[0]); |
| 1802 | close(childout[1]); |
| 1803 | close(execfail[0]); |
| 1804 | |
| 1805 | /* In practice, low fds are all open, so we don't have |
| 1806 | * to handle those horrible cases */ |
| 1807 | assert(childin[1] > 2); |
| 1808 | assert(childout[0] > 2); |
| 1809 | if (dup2(childin[1], STDOUT_FILENO) == -1) |
| 1810 | err(1, "Failed to duplicate fd to stdout"); |
| 1811 | close(childin[1]); |
| 1812 | if (dup2(childout[0], STDIN_FILENO) == -1) |
| 1813 | err(1, "Failed to duplicate fd to stdin"); |
| 1814 | close(childout[0]); |
| 1815 | closefrom_limit(0); |
| 1816 | closefrom(3); |
no test coverage detected