Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 7 additions & 8 deletions workloads/cln/Dockerfile.coverage
Original file line number Diff line number Diff line change
Expand Up @@ -65,14 +65,13 @@ RUN git clone --depth 1 --branch ${CLN_VERSION} --recurse-submodules \
https://github.com/ElementsProject/lightning.git /cln
WORKDIR /cln
RUN pip3 install --break-system-packages mako
# Currently CLN does an unnecessary SIGKILL of per-peer subdaemons (openingd,
# channeld, etc.) during node shutdown. If the SIGKILL arrives before the
# subdaemon shuts down gracefully on its own, we lose coverage profile data
# (profraw files) for that subdaemon.
#
# Remove the SIGKILL to ensure we get full coverage data.
RUN grep -q 'kill(sd->pid, SIGKILL)' lightningd/subd.c && \
sed -i '/kill(sd->pid, SIGKILL)/d' lightningd/subd.c
# When a per-peer subdaemon (openingd, channeld, etc.) dies mid-run (e.g. after
# a channel error), lightningd SIGKILLs it. SIGKILL skips the atexit handler
# that writes the profraw file, so we lose that subdaemon's entire coverage
# profile. Close its socket instead, which makes it exit by itself, only killing
# as a fallback.
COPY workloads/cln/patches/subd-coverage-shutdown.patch .
RUN git apply subd-coverage-shutdown.patch
# Reduce the block-polling interval from the 30s default to 2s. CLN only
# notices newly confirmed transactions when this poll runs, so shorten the
# interval to make block-related events available to scenarios promptly.
Expand Down
33 changes: 33 additions & 0 deletions workloads/cln/patches/subd-coverage-shutdown.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
Let a dying subdaemon exit by itself before SIGKILLing it.

SIGKILL skips the atexit handler that writes the subdaemon's LLVM profile data,
so a coverage build loses every line it executed.

Closing our end of its socket gets it to exit on its own, flushing the profraw
file. This is what subd_shutdown() already does for the global daemons, so we
apply the same approach here for destroy_subd().

Closing is not always enough -- subdaemons can still block on the HSM fd, which
causes lightningd to wait several minutes for it. So keep the kill as a
fallback after 5s.

--- a/lightningd/subd.c
+++ b/lightningd/subd.c
@@ -611,9 +611,17 @@
if (!sd->must_not_exit) {
log_debug(sd->log,
"Status closed, but not exited. Killing");
+ sd->conn = tal_free(sd->conn);
+ for (size_t i = 0; i < 500; i++) {
+ if (waitpid(sd->pid, &status,
+ WNOHANG) > 0)
+ goto reaped;
+ usleep(10000);
+ }
kill(sd->pid, SIGKILL);
}
waitpid(sd->pid, &status, 0);
+ reaped:
fail_if_subd_fails = false;
break;
case -1: