[erlang-questions] : Subtle behaviour of Erlang scheduler

Ulf Wiger (TN/EAB) ulf.wiger@REDACTED
Tue May 29 12:11:38 CEST 2007


me@REDACTED wrote
> 
> Dear Ulf, I know you're not talking on behalf of OTP group 
> :-) My mail would just say that if we (the community of 
> Erlang users and
> developers) want Erlang to be used as a general-purpose 
> robust solution for different problems and applications, we 
> should communicate, talk, discuss, exchange ideas and propose 
> new or better features for the platform we use on our 
> every-day work (or fun), thinking also to new and possibly 
> unexplored fields where Erlang features can be exploited.

So, for the purposes of discussion, how would you feel 
about a change as the one I suggested - do simply disallow
on-demand code loading for high priority processes?

I would assume that it wouldn't hurt the existing code
base, since there are so few processes running on 
high priority, and the designers have thought carefully
about these aspects...

... or so I thought, until I implemented it.

Below is a diff for the error_handler.erl. 
It simply checks if the process has priority
high or max, and if so doesn't call on the code
server.

Interestingly, running with this patch causes 
global_group to crash at startup with an undef,
when calling net_kernel. :-D

I fixed that temporarily by moving the call to 
process_flag(priority, max) to the end of the init/1
function in global_group.erl.

On-demand code loading obviously works for global_group
because there isn't any high-priority process caught in
a busy loop, as in your example. Here, the global_group
process will simply yield until the code is available
and then continue. Also, this code is guaranteed to 
run without interference as long as you don't add the 
flag -risky_shell (or something), since it happens 
during the kernel boot process.

Anyway - see how easy it is to break existing code? ;-)

BR,
Ulf W

$> diff error_handler.erl
$OTP_ROOT/lib/kernel-2.10.11/src/error_handler.erl
73,94c73,86
<     {priority, Prio} = process_info(self(), priority),
<     if Prio == high; Prio == max ->
<           case erlang:module_loaded(Module) of
<               true -> {module, Module};
<               false -> false
<           end;
<        true ->
<           case whereis(code_server) of
<               %% Perhaps double fault should be detected in
code:ensure_loaded/1 
<               %% instead, since this error handler cannot know whether
the 
<               %% code server can resolve the problem or not.
<               %% An {error, Reason} return from there would crash the
code server and 
<               %% bring down the node.
<               Self ->
<                   Error = "The code server called the unloaded module
`" ++
<                       atom_to_list(Module) ++ "'",
<                   halt(Error);
<               Pid when pid(Pid) ->
<                   code:ensure_loaded(Module);
<               _ ->
<                   init:ensure_loaded(Module)
<           end
---
>     case whereis(code_server) of
>       %% Perhaps double fault should be detected in
code:ensure_loaded/1 
>       %% instead, since this error handler cannot know whether the 
>       %% code server can resolve the problem or not.
>       %% An {error, Reason} return from there would crash the code
server and 
>       %% bring down the node.
>       Self ->
>           Error = "The code server called the unloaded module `" ++
>               atom_to_list(Module) ++ "'",
>           halt(Error);
>       Pid when pid(Pid) ->
>           code:ensure_loaded(Module);
>       _ ->
>           init:ensure_loaded(Module)




More information about the erlang-questions mailing list