diff options
author | John Högberg <[email protected]> | 2018-11-13 11:55:48 +0100 |
---|---|---|
committer | John Högberg <[email protected]> | 2018-11-13 16:43:49 +0100 |
commit | d15bd6b9366ff4eef81ec9c4bcc875dfe694fe98 (patch) | |
tree | 01fae71e46df08266e586c2048ecff11bc7e58f8 /erts/preloaded/src/prim_file.erl | |
parent | d9682b02b81fa6e23e554b6e017650eb89ecebed (diff) | |
download | otp-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/prim_file.erl')
-rw-r--r-- | erts/preloaded/src/prim_file.erl | 18 |
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 |