GeezerVison is showing github.com — watch mode crashes with `Not allowed to signal` when a build is cancelled · Issue #16053 · ocaml/dune
watch mode crashes with Not allowed to signal when a build is cancelled #16053DescriptionDescription
A long-running dune build @check --watch died with the internal error below.
Source files were changing while it ran, so the current build was being
cancelled and restarted, and the crash landed on one of those cancellations.
Directory and module names are replaced with <dir> and <Module>, and the
repeated Fiber__Scheduler.exec frames are trimmed. Nothing else is edited.
Internal error! Please report to https://github.com/ocaml/dune/issues,
providing the file _build/trace.csexp, if possible. This includes build
commands, message logs, and file paths.
Description:
("Not allowed to signal", { signal = TERM; pid = pid 33971 })
Raised at Stdune__Code_error.raise in file "stdune__Code_error.ml", line 11,
characters 30-62
Called from Dune_scheduler__Process_watcher.kill_process_group in file
"dune_scheduler__Process_watcher.ml", line 22, characters 12-38
Called from Dune_scheduler__Scheduler.wait_for_build_process.(fun) in file
"dune_scheduler__Scheduler.ml", line 312, characters 15-83
Called from Fiber__Cancel.with_handler.(fun) in file "fiber__Cancel.ml", line
100, characters 20-32
Called from Fiber__Scheduler.exec in file "fiber__Scheduler.ml", line 77,
characters 8-11
[...]
-> required by
("execute-rule",
{ id = 463355
; info =
From_dune_file
{ pos_fname = "<dir>/dune"
; start = { pos_lnum = 1; pos_bol = 0; pos_cnum = 0 }
; stop = { pos_lnum = 18; pos_bol = 163; pos_cnum = 172 }
}
})
-> required by ("<unnamed>", ())
-> required by
("build-file",
In_build_dir
"default/<dir>/.test.eobjs/byte/<Module>.cmt")
-> required by ("build-alias", { dir = "default/<dir>"; name = "check" })
Pid.kill raises a Code_error on EPERM, and kill_process_group reaches it
from the ~on_cancel handler of Scheduler.wait_for_build_process, so an
EPERM from kill(2) brings down the whole server instead of failing the one
job. Dead is already tolerated on that path.
An EPERM there does not need an exotic pid. The macOS kill(2) man page says
that when signalling a process group, EPERM is returned "if any members of the
group could not be signaled", so one member the uid may not signal is enough,
and a pid that was reaped and reused elsewhere on the machine reports EPERM
rather than ESRCH. I have not confirmed which of the two happened here.
Would returning Not_allowed from Pid.kill and ignoring it at this call site,
the way Dead is ignored, be the right shape?
Reproduction
None. It wants an EPERM from kill(2) on the action's process group, which I
have not managed to force without root, and it has not recurred since. The
watcher now writes its trace outside _build so the next occurrence survives a
restart.
Specifications
- Version of
dune: 3.24.1-912-g5e10796, a dev build of main at
5e1079629ad9e987dd20c7a10218f97833254d7b
- Version of
ocaml: 5.4.1
- Operating system: macOS 27.0 on arm64
ActivityAlizter commented on Aug 20, 2026 --trace-file is not required to get a build trace, are you certain _build/trace.csexp doesn't exist?
samoht commented on Aug 20, 2026 You are right, --trace-file only changes where the trace goes, and my note was wrong.
The file does exist. It does not cover this crash, though. _build/trace.csexp in that workspace opens with a config/init record timestamped this morning, so it holds the current watch session, and the crash was the day before. The backup added in #14269 does not reach back either: trace.csexp.old begins at the restart that followed the crashing session. The watcher has been restarted a few times since and the backup is one generation deep, so the trace covering the crash has been rotated out. I have corrected that sentence in the issue body.
From now on I will point the long-lived watcher at a --trace-file outside _build, so a restart does not take the evidence with it, and I will keep whatever the next occurrence produces. The default trace opens with the full environment and carries every command line, so rather than post one whole, tell me which slice is useful and I will pull that out. added a commit that references this issue on Aug 20, 2026This issue will close once commit 7b43b69 is merged into the 'master' branch.7b43b69 added a commit that references this issue on Aug 20, 2026This issue will close once commit c4a706d is merged into the 'main' branch.c4a706d added a commit that references this issue on Nov 12, 2026This issue will close once commit 5493d2f is merged into the 'master' branch.5493d2f
MetadataMetadataDevelopmentNo branches or pull requestsIssue actions
|