From 05e49fe1c1c8322ecf69b0df952d277983900cf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-S=C3=A9bastien=20P=C3=A9dron?= Date: Wed, 27 Nov 2024 18:12:29 +0100 Subject: [PATCH] cover: Fix a race condition in how the server is started as part of a call MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Before sending a message to the cover server, the `call` function checks if the server is running, starting it if it does not. However, there is no locking/atomicity between the check and the start. If there is a concurrent call, the server might be started in parallel by another process and the `start()` call would return `{error, {already_started, _}}`. This causes the function to fail with a `badmatch` exception. The code now accepts that the server is running after seeing the server as stopped and retrying the call. V2: Fix coding style by applying a suggested patch from Björn Gustavsson. V3: Fix incorrect matching of `start()` return value: the correct pattern in `{error, {already_started, _}}`, not `{already_started, _}`. Found by Dialyzer, reported by Björn Gustavsson. Co-authored-by: Björn Gustavsson --- lib/tools/src/cover.erl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/tools/src/cover.erl b/lib/tools/src/cover.erl index 67b9841b2002..b2791760663a 100644 --- a/lib/tools/src/cover.erl +++ b/lib/tools/src/cover.erl @@ -1143,7 +1143,10 @@ call(Request) -> Ref = erlang:monitor(process,?SERVER), receive {'DOWN', Ref, _Type, _Object, noproc} -> erlang:demonitor(Ref), - {ok,_} = start(), + case start() of + {ok,_} -> ok; + {error,{already_started,_}} -> ok + end, call(Request) after 0 -> ?SERVER ! {self(),Request},