aboutsummaryrefslogtreecommitdiffstats
path: root/erts/preloaded/src
diff options
context:
space:
mode:
authorJohn Högberg <[email protected]>2018-11-13 11:55:48 +0100
committerJohn Högberg <[email protected]>2018-11-13 16:43:49 +0100
commitd15bd6b9366ff4eef81ec9c4bcc875dfe694fe98 (patch)
tree01fae71e46df08266e586c2048ecff11bc7e58f8 /erts/preloaded/src
parentd9682b02b81fa6e23e554b6e017650eb89ecebed (diff)
downloadotp-d15bd6b9366ff4eef81ec9c4bcc875dfe694fe98.tar.gz
otp-d15bd6b9366ff4eef81ec9c4bcc875dfe694fe98.tar.bz2
otp-d15bd6b9366ff4eef81ec9c4bcc875dfe694fe98.zip
Avoid closing files in gc/monitor callbacks
Closing files in these callbacks could block scheduler progress and cause major system instability. We now defer these operations to a dedicated process instead. This process may in turn block forever and prevent further orphaned files from being closed, but it will keep the emulator itself from misbehaving.
Diffstat (limited to 'erts/preloaded/src')
-rw-r--r--erts/preloaded/src/prim_file.erl18
1 files changed, 17 insertions, 1 deletions
diff --git a/erts/preloaded/src/prim_file.erl b/erts/preloaded/src/prim_file.erl
index 6d85868183..5fc22bc582 100644
--- a/erts/preloaded/src/prim_file.erl
+++ b/erts/preloaded/src/prim_file.erl
@@ -83,6 +83,15 @@ internal_normalize_utf8(_) ->
is_translatable(_) ->
erlang:nif_error(undefined).
+%% This is a janitor process used to close files whose controlling process has
+%% died. The emulator will be torn down if this is killed.
+delayed_close_loop() ->
+ receive
+ {close, FRef} when is_reference(FRef) -> delayed_close_nif(FRef);
+ _ -> ok
+ end,
+ delayed_close_loop().
+
%%
%% Returns {error, Reason} | {ok, BytesCopied}
@@ -95,7 +104,12 @@ copy(#file_descriptor{module = ?MODULE} = Source,
file:copy_opened(Source, Dest, Length).
on_load() ->
- ok = erlang:load_nif(atom_to_list(?MODULE), 0).
+ Pid = spawn(fun() ->
+ process_flag(trap_exit, true),
+ delayed_close_loop()
+ end),
+ true = register(erts_prim_file, Pid),
+ ok = erlang:load_nif(atom_to_list(?MODULE), Pid).
open(Name, Modes) ->
%% The try/catch pattern seen here is used throughout the file to adhere to
@@ -482,6 +496,8 @@ truncate_nif(_FileRef) ->
erlang:nif_error(undef).
get_handle_nif(_FileRef) ->
erlang:nif_error(undef).
+delayed_close_nif(_FileRef) ->
+ erlang:nif_error(undef).
%%
%% Quality-of-life helpers