erlang: exit-signal propagation + trap_exit (+11 tests)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Has been cancelled
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Has been cancelled
This commit is contained in:
@@ -502,6 +502,65 @@
|
||||
(= (len (er-proc-field (er-mk-pid 1) :monitored-by)) 0)))
|
||||
true)
|
||||
|
||||
;; ── exit-signal propagation + trap_exit ────────────────────────
|
||||
(er-eval-test "process_flag default false"
|
||||
(nm (ev "process_flag(trap_exit, true)")) "false")
|
||||
(er-eval-test "process_flag returns prev"
|
||||
(nm (ev "process_flag(trap_exit, true), process_flag(trap_exit, false)"))
|
||||
"true")
|
||||
|
||||
;; Monitor fires on normal exit.
|
||||
(er-eval-test "monitor DOWN normal"
|
||||
(nm (ev "P = spawn(fun () -> ok end), monitor(process, P), receive {'DOWN', _, process, _, R} -> R end"))
|
||||
"normal")
|
||||
|
||||
;; Monitor fires on abnormal exit.
|
||||
(er-eval-test "monitor DOWN abnormal"
|
||||
(nm (ev "P = spawn(fun () -> exit(boom) end), monitor(process, P), receive {'DOWN', _, process, _, R} -> R end"))
|
||||
"boom")
|
||||
|
||||
;; Monitor's ref appears in DOWN message.
|
||||
(er-eval-test "monitor DOWN ref matches"
|
||||
(nm (ev "P = spawn(fun () -> exit(bye) end), Ref = monitor(process, P), receive {'DOWN', Ref, process, _, _} -> ok_match end"))
|
||||
"ok_match")
|
||||
|
||||
;; Two monitors -> both fire.
|
||||
(er-eval-test "two monitors both fire"
|
||||
(ev "P = spawn(fun () -> exit(crash) end), monitor(process, P), monitor(process, P), receive {'DOWN', _, _, _, _} -> ok end, receive {'DOWN', _, _, _, _} -> 2 end")
|
||||
2)
|
||||
|
||||
;; trap_exit + link + abnormal exit -> {'EXIT', From, Reason} message.
|
||||
(er-eval-test "trap_exit catches abnormal"
|
||||
(nm (ev "process_flag(trap_exit, true), P = spawn(fun () -> exit(boom) end), link(P), receive {'EXIT', _, R} -> R end"))
|
||||
"boom")
|
||||
|
||||
;; trap_exit + link + normal exit -> {'EXIT', From, normal}.
|
||||
(er-eval-test "trap_exit catches normal"
|
||||
(nm (ev "process_flag(trap_exit, true), P = spawn(fun () -> ok end), link(P), receive {'EXIT', _, R} -> R end"))
|
||||
"normal")
|
||||
|
||||
;; Cascade exit: A links B, B dies abnormally, A dies with same reason.
|
||||
(er-eval-test "cascade reason"
|
||||
(do
|
||||
(ev "A = spawn(fun () -> B = spawn(fun () -> exit(crash) end), link(B), receive forever -> ok end end), receive after 0 -> ok end")
|
||||
(nm (er-proc-field (er-mk-pid 1) :exit-reason)))
|
||||
"crash")
|
||||
|
||||
;; Normal exit doesn't cascade (without trap_exit) — A's body returns
|
||||
;; "survived" via the `after` clause and A dies normally.
|
||||
(er-eval-test "normal exit no cascade"
|
||||
(do
|
||||
(ev "A = spawn(fun () -> B = spawn(fun () -> ok end), link(B), receive {'EXIT', _, _} -> got_exit after 50 -> survived end end), receive after 0 -> ok end")
|
||||
(list
|
||||
(nm (er-proc-field (er-mk-pid 1) :exit-reason))
|
||||
(nm (er-proc-field (er-mk-pid 1) :exit-result))))
|
||||
(list "normal" "survived"))
|
||||
|
||||
;; Monitor without trap_exit: monitored proc abnormal doesn't kill the monitor.
|
||||
(er-eval-test "monitor doesn't cascade"
|
||||
(nm (ev "P = spawn(fun () -> exit(boom) end), monitor(process, P), receive {'DOWN', _, _, _, _} -> alive end"))
|
||||
"alive")
|
||||
|
||||
(define
|
||||
er-eval-test-summary
|
||||
(str "eval " er-eval-test-pass "/" er-eval-test-count))
|
||||
|
||||
Reference in New Issue
Block a user