Skip to content

Commit

Permalink
Fix random crashes and subsequent test failures in umbrella apps
Browse files Browse the repository at this point in the history
There is a possibility of a race condition on stopping/restarting
ExUnit/AssertValue apps more frequent within umbrella projects.
When ExUnit is stopped, AssertValue may still attempt to flush the
StringIO. This may lead to various errors.
Changed code flushing ExUnit's IO to handle these states.

Also changed AssertValue.Server to always restart on errors
(default GenServer behaviour)
  • Loading branch information
smetana committed Oct 26, 2023
1 parent 3476fc1 commit 5167c5c
Showing 1 changed file with 21 additions and 3 deletions.
24 changes: 21 additions & 3 deletions lib/assert_value/server.ex
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
defmodule AssertValue.Server do
use GenServer, restart: :temporary
use GenServer
import AssertValue.StringTools

def start_link(args) do
Expand Down Expand Up @@ -65,8 +65,26 @@ defmodule AssertValue.Server do
end

def handle_cast({:flush_ex_unit_io}, state) do
contents = StringIO.flush(state.captured_ex_unit_io_pid)
if contents != "", do: IO.write(contents)
# There is a possibility of a race condition occurring when
# stopping/restarting ExUnit/AssertValue applications within umbrella apps.
#
# When ExUnit is stopped, AssertValue may still attempt to flush the
# StringIO. There are two potential states to consider:
#
# 1. if captured_ex_unit_io_pid is nil, this will result in
# "no function clause matching in StringIO.flush/1."
# 2. if captured_ex_unit_io_pid is not nil, but the process is stopped,
# this will result in "(EXIT) no process: the process is not alive..."
#
# Code below handles both of these cases
try do
if state.captured_ex_unit_io_pid do
contents = StringIO.flush(state.captured_ex_unit_io_pid)
if contents != "", do: IO.write(contents)
end
catch
:exit, {:noproc, _} -> :ok
end
{:noreply, state}
end

Expand Down

0 comments on commit 5167c5c

Please sign in to comment.