Detecting Concurrency Errors
- f Erlang Programs
Detecting Concurrency Errors of Erlang Programs Using Systematic - - PowerPoint PPT Presentation
Detecting Concurrency Errors of Erlang Programs Using Systematic Testing Kostis Sagonas kostis@it.uu.se Outline Erlang Concurrency errors and their sources Systematic Concurrency Testing Concuerror & Demo Techniques to
2017-02-01 Dagstuhl 2017
2017-02-01 Dagstuhl 2017
2017-02-01 Dagstuhl 2017
Concurrent execution is difficult to reason about
Rare process interleaving results in bugs that are
hard to anticipate difficult to find, reproduce, and debug (“Heisenbugs”) hard to be sure whether they are really fixed
Big productivity problem: it can waste significant
Can have severe consequences
2017-02-01 Dagstuhl 2017
2017-02-01 Dagstuhl 2017
Scheduling non-determinism
Interleaving non-determinism
Processes can race to access shared resources Processes can be preempted at arbitrary points
Timing non-determinism
Memory model effects Input/data non-determinism
Programs can be used in a variety of ways Non-deterministic calls (e.g. random())
2017-02-01 Dagstuhl 2017
x := 1; y := 1; x := 1; y := 1; x := 2; y := 2; x := 2; y := 2;
2,1 2,1 1,0 1,0 0,0 0,0 1,1 1,1 2,2 2,2 2,2 2,2 2,1 2,1 2,0 2,0 2,1 2,1 2,2 2,2 1,2 1,2 2,0 2,0 2,2 2,2 1,1 1,1 1,1 1,1 1,2 1,2 1,0 1,0 1,2 1,2 1,1 1,1
y := 1; y := 1; x := 1; x := 1; y := 2; y := 2; x := 2; x := 2;
2017-02-01 Dagstuhl 2017
2017-02-01 Dagstuhl 2017
2017-02-01 Dagstuhl 2017
Easy to use Scalable
Applicable to “real-world” programs
Precise
Any error found is possible to occur Does not introduce new behaviors
Coverage
All concurrency errors (for a test) can be found Captures all scheduling non-determinism Exhaustively explores this non-determinism
2017-02-01 Dagstuhl 2017
pong() -> Self = self(), Pid = spawn(fun() -> ping(Self) end), register(ping_pong, Pid), receive ping -> ok end. ping(P) -> P ! ping.
pong_test() ->
2017-02-01 Dagstuhl 2017
Checked 5 interleaving( s) . 1 error found. Error type : Exception Details : {badarg,[{erlang,register,[ping_pong,<...>],[]}, ... Process P1 spawns process P1.1 Process P1.1 sends message `ping` to process P1 Process P1.1 exits (normal) Process P1 registers process P1.1 (dead) as `ping_pong` Process P1 exits ("Exception")
2017-02-01 Dagstuhl 2017
action() -> Bank = self(), register(bank, Bank), Cust = spawn(fun() -> bank ! money end), God = spawn(fun() -> receive Msg -> ok end end), receive money -> God ! bank_got_money end.
action() -> Bank = self(), register(bank, Bank), Cust = spawn(fun() -> bank ! money end), God = spawn(fun() -> receive Msg -> ok end end), Thief = spawn(fun() -> unregister(bank), register(bank, self()), receive money -> God ! thief_got_money after 0 -> God ! theft_failed end end), receive money -> God ! bank_got_money end.
2017-02-01 Dagstuhl 2017
Initially: x = y = … = z = 0 Thread 1: x := 1 Thread 2: y := 1
…
Thread N: z := 1
2017-02-01 Dagstuhl 2017
Thread 1: x := 1 Thread 2: y := 1
x= 1 y= 0 x= 0 y= 0
Thread 1: x := 1 Thread 2: y:= 1
x= 0 y= 1 x= 1 y= 1
Thread 1: x := 1 Thread 2: y := 1
2017-02-01 Dagstuhl 2017
2017-02-01 Dagstuhl 2017
2017-02-01 Dagstuhl 2017
Benchmark Traces explored Time Classic Source Optimal Classic Source Optimal
filesystem (14) 4 2 2 0.54s 0.36s 0.35s filesystem (16) 64 8 8 8.13s 1.82s 1.78s filesystem (18) 1024 32 32 2m11s 8.52s 8.86s filesystem (19) 4096 64 64
8m33s 18.62s 19.57s
Classic
2017-02-01 Dagstuhl 2017
Benchmark Traces explored Time Classic Source Optimal Classic Source Optimal
indexer (12) 78 8 8 0.74s 0.11s 0.10s indexer (15) 341832 4096 4096
56m20s 50.24s 52.35s
Optimal
2017-02-01 Dagstuhl 2017
Benchmark Traces explored Time Classic Source Optimal Classic Source Optimal
dialyzer 12436 3600 3600 14m46s 5m17s 5m46s gproc 14080 8328 8104 3m3s 1m45s 1m57s poolboy 6018 3120 2680 3m2s 1m28s 1m20s rushhour 793375 536118 528984 145m 102m 106m
LOC: 44596 (dialyzer), 9446 (gproc), 79732 (poolboy), 917 (rushhour)