Example of OTP deadlock via the application controller.
In OTP, the application environment is handled via a ETS table, which
is accessed via the application_controller
process. Whilst reading
an environment variable is implemented as a mere lookup operation,
writes are serialized through the application controller.
In other words, it is not possible to set an environment variable
from a terminate/1
callback in a gen_server which traps exits,
since in case of application termination the application controller is
busy shutting down the application itself and cannot handle other
requests, causing a deadlock.
To reproduce it:
$ erl
Erlang R15B03 (erts-5.9.3.1) [source] [64-bit] [smp:8:8] [async-threads:0] [hipe] [kernel-poll:false]
Eshell V5.9.3.1 (abort with ^G)
1> c(deadlock).
{ok,deadlock}
2> c(deadlock_sup).
{ok,deadlock_sup}
3> c(deadlock_app..
{ok,deadlock_app}
4> application:start(deadlock).
ok
5> application:stop(deadlock).
ok
6>
=ERROR REPORT==== 9-Dec-2014::09:37:34 ===
** Generic server deadlock terminating
** Last message in was {'EXIT',<0.52.0>,shutdown}
** When Server state == {state}
** Reason for termination ==
** {timeout,{gen_server,call,[application_controller,{set_env,sasl,x,y}]}}
=INFO REPORT==== 9-Dec-2014::09:37:34 ===
application: deadlock
exited: stopped
type: temporary