aboutsummaryrefslogtreecommitdiffstats
path: root/erts/preloaded/src/erts_dirty_process_signal_handler.erl
diff options
context:
space:
mode:
Diffstat (limited to 'erts/preloaded/src/erts_dirty_process_signal_handler.erl')
-rw-r--r--erts/preloaded/src/erts_dirty_process_signal_handler.erl103
1 files changed, 103 insertions, 0 deletions
diff --git a/erts/preloaded/src/erts_dirty_process_signal_handler.erl b/erts/preloaded/src/erts_dirty_process_signal_handler.erl
new file mode 100644
index 0000000000..381f81ef14
--- /dev/null
+++ b/erts/preloaded/src/erts_dirty_process_signal_handler.erl
@@ -0,0 +1,103 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(erts_dirty_process_signal_handler).
+
+-export([start/0]).
+
+%%
+%% The erts_dirty_process_signal_handler is started at
+%% VM boot by the VM. It is a spawned as a system
+%% process, i.e, the whole VM will terminate if
+%% this process terminates.
+%%
+start() ->
+ process_flag(trap_exit, true),
+ msg_loop().
+
+msg_loop() ->
+ _ = receive
+ Request ->
+ try
+ handle_request(Request)
+ catch
+ _ : _ ->
+ %% Ignore all failures;
+ %% someone passed us garbage...
+ ok
+ end
+ end,
+ msg_loop().
+
+handle_request(Pid) when is_pid(Pid) ->
+ handle_incoming_signals(Pid, 0);
+handle_request({Requester, Target, Prio,
+ {SysTaskOp, ReqId, Arg} = Op} = Request) ->
+ case handle_sys_task(Requester, Target, SysTaskOp, ReqId, Arg, 0) of
+ done ->
+ ok;
+ busy ->
+ self() ! Request;
+ normal ->
+ %% Target has stopped executing dirty since the
+ %% initial request was made. Dispatch the
+ %% request to target and let it handle it itself...
+ case erts_internal:request_system_task(Requester,
+ Target,
+ Prio,
+ Op) of
+ ok ->
+ ok;
+ dirty_execution ->
+ %% Ahh... It began executing dirty again...
+ handle_request(Request)
+ end
+ end;
+handle_request(_Garbage) ->
+ ignore.
+
+%%
+%% ----------------------------------------------------------------------------
+%%
+
+handle_incoming_signals(Pid, 5) ->
+ self() ! Pid; %% Work with other requests for a while...
+handle_incoming_signals(Pid, N) ->
+ case erts_internal:dirty_process_handle_signals(Pid) of
+ more -> handle_incoming_signals(Pid, N+1);
+ _Res -> ok
+ end.
+
+handle_sys_task(Requester, Target, check_process_code, ReqId, Module, N) ->
+ case erts_internal:check_dirty_process_code(Target, Module) of
+ Bool when Bool == true; Bool == false ->
+ Requester ! {check_process_code, ReqId, Bool},
+ done;
+ busy ->
+ case N > 5 of
+ true ->
+ busy;
+ false ->
+ handle_sys_task(Requester, Target, check_process_code,
+ ReqId, Module, N+1)
+ end;
+ Res ->
+ Res
+ end.