[erlang-questions] Some problem abount exit signal?

Hynek Vychodil hynek@REDACTED
Thu Dec 9 17:21:57 CET 2010


On Thu, Dec 9, 2010 at 1:03 AM, Robert Virding
<robert.virding@REDACTED> wrote:
> Yes, the problem is not with the "sender" of the signal. exit/1 and exit/2 are different: exit/1 ends the process which results in exit reason being sent as a signal to the processes in the link set; while exit/2 fakes a signal to the receiving process *as if* the process had died.
>
> The problem occurs in the "receiving" process. If it receives a 'kill' signal it will behave differently depending on how the signal was sent. There should not be two different behaviours attached to one signal, kill, depending on how it was sent. A 'kill' should always be a 'kill' in the same way as a 'normal' is always a 'normal'. It is really not different if the signal 'normal' caused a process to terminate when sent with exit/2 but be ignored if the sending process dies with exit(normal).
>
> Or writing a server where a request message means different things depending on who sent them.
>
> Different behaviours should be caused by things with different names.
>
> Robert
>

>From point of receiver view if I receive signal {'EXIT', self(), kill}
I can be sure it is not produced by exit/2 kill because it is
untrappable so I can be sure it is fake. If I receive {'EXIT', PID,
kill} when PID =/= self() I can be sure this PID was not killed by
exit/2 kill because it would be translated to killed. So I can't be
confused, simply when I receive {'EXIT', _, kill} I'm sure it is not
produced by exit/2 kill message. From point of receiver view only
{'EXIT', _, Reason} when Reason =:= killed; Reason =:= normal has
special meanings. I'm pretty happy with it. Untrappable 'kill' even
doesn't have to have {'EXIT', _, kill} format because I can't ever see
it. It happen behind the scene, if it is not observable I can't say
there is any inconsistency.

Only news for me from this discussion is that exit/1 is catchable and
exit/2 isn't which I didn't realize before. It is little bit annoying
they have same name even they do something absolutely different. One
raises exception and other sends message. There is nothing wrong with
'kill' but with exit/1 and exit/2.

>
> ----- "Hynek Vychodil" <hynek@REDACTED> wrote:
>
>> I few moment I think there is the bug but after some experiments I
>> have to say it is pretty clear here.
>>
>> exit/1 doesn't sends any signal. It is simple "local exception" -
>> termination which is catchable in catch and try. When it is not catch
>> process terminates as usual and sends exit message to linked
>> processes
>> with reason. 'kill' reason is send as any other reason. There is not
>> special meaning except 'normal' ...
>>
>> exit/2 sends message and only when there is 'kill' reason it makes
>> "untrappable" kill and is translated to 'killed' exit message to
>> linked processes. exit/2 sends message which doesn't have "local"
>> behavior even I send it to myself because it is just like any other
>> message. I.e. it is uncatchable by catch or try. When exit signal is
>> not trapped i.e. it is untrappable (only direct exit/2 'kill') or is
>> not 'normal' and exit signals are not trapped then process dies and
>> exit signal is resend to linked processes with reason translation to
>> 'killed' just only for untrappable 'kill'.
>>
>> It makes perfect sense for me and I can't see there any bug or
>> misconception. Maybe documentation should be more explicit there.
>>
>> On Sun, Dec 5, 2010 at 2:36 AM, Robert Virding
>> <robert.virding@REDACTED> wrote:
>> > Yes, this is how it works, but I definitely consider this to be a
>> bug. To elaborate with a simple example:
>> >
>> > 1> self().
>> > <0.31.0>
>> > 2> spawn_link(fun () -> exit(kill) end).
>> > ** exception exit: killed
>> > 3> self().
>> > <0.35.0>
>> >
>> > Here I have received 'kill' signal and died as I should. Now I trap
>> exits:
>> >
>> > 4> process_flag(trap_exit, true).
>> > false
>> > 5> spawn_link(fun () -> exit(kill) end).
>> > <0.39.0>
>> > 6> flush().
>> > Shell got {'EXIT',<0.39.0>,kill}
>> > ok
>> >
>> > This time I received a trappable 'kill' signal. Finally I explicitly
>> send the 'kill' signal to me:
>> >
>> > 7> Self = self().
>> > <0.35.0>
>> > 8> process_flag(trap_exit, true).          %Just to be explicit
>> > true
>> > 9> spawn_link(fun () -> exit(Self, kill) end).
>> > ** exception exit: killed
>> > 10> self().
>> > <0.45.0>
>> >
>> > And this time I received an untrappable 'kill' signal.
>> >
>> > This means that there are two different types of 'kill' signals,
>> trappable and untrappable, in the systems depending on how they were
>> sent. This is illogical and unclear as there should not be two
>> different signals with the same name which behave differently. It is
>> definitely a bug which should be fixed. I see two (three) different
>> solutions:
>> >
>> > 1. Make it so that a process which does exit(kill) sends a real,
>> untrappable kill signal to its link set (which then in turn transmit
>> 'killed').
>> >
>> > 2. Make it so that a process which does exit(kill) behaves as if it
>> were killed and so transmits 'killed' to its link set.
>> >
>> > 3. Leave it as it is and create a
>> 'properly_behaving_really_untrappable_kill' signal which behaves
>> sensibly.
>> >
>> > I think the first option is the best.
>> >
>> > Robert
>> >
>> > P.S. Now to copy all this to erlang-bugs.
>> >
>> > P.P.S. I have just noticed that doing exit(self(), normal) kills me
>> while some other process doing exit(Me, normal) doesn't. Sigh, so
>> normal isn't normal.
>> >
>> >
>> > ----- "Ulf Wiger" <ulf.wiger@REDACTED> wrote:
>> >
>> >> Process C terminates itself with exit(kill). The atom 'kill'
>> >> is not special in this case, but simply a normal exit reason.
>> >>
>> >> A propagated exit signal can never act as a kill signal in the
>> >> first place, but here, not even the original exit is an
>> untrappable
>> >> kill.
>> >>
>> >> Try:
>> >>
>> >> Eshell V5.8.1  (abort with ^G)
>> >> 1> self().
>> >> <0.31.0>
>> >> 2> catch exit(kill).
>> >> {'EXIT',kill}
>> >> 3> self().
>> >> <0.31.0>
>> >>
>> >> BR,
>> >> Ulf W
>> >>
>> >> On 2 Dec 2010, at 05:37, sky wrote:
>> >>
>> >> > Hi guys,
>> >> >
>> >> > In the Joe's book <<progamming erlang>>, page 163, there are
>> some
>> >> description about exit signal :
>> >> >
>> >> > When an exit signal arrives at a process, then a number of
>> >> different
>> >> > things might happen. What happens depends upon the state of the
>> >> > receiving process and upon the value of the exit signal and is
>> >> deter-
>> >> > mined by the following table:
>> >> > <moz-screenshot.png>
>> >> >
>> >> > but when use edemo1:start(true, {die, kill}), the result is:
>> >> >
>> >> > edemo1:start(true, {die,kill}).
>> >> > Process b received {'EXIT',<0.73.0>,kill}
>> >> > process b (<0.72.0>) is alive
>> >> > process c (<0.73.0>) is dead
>> >> > ok
>> >> > Why process b is alive? Cause as the descripion in this book,
>>  when
>> >> the exit signal
>> >> > {'EXIT',<0.73.0>,kill}
>> >> > arrived, the process b will die and broadcast the exit signal
>> killed
>> >> to the link set.
>> >> >
>> >> > the souce code of edemo1 module as following:
>> >> >
>> >> > %% ---
>> >> > %%  Excerpted from "Programming Erlang",
>> >> > %%  published by The Pragmatic Bookshelf.
>> >> > %%  Copyrights apply to this code. It may not be used to create
>> >> training material,
>> >> > %%  courses, books, articles, and the like. Contact us if you are
>> in
>> >> doubt.
>> >> > %%  We make no guarantees that this code is fit for any purpose.
>> >> > %%  Visit http://www.pragmaticprogrammer.com/titles/jaerlang for
>> >> more book information.
>> >> > %%---
>> >> >
>> >> > -module(edemo1).
>> >> > -export([start/2]).
>> >> >
>> >> > start(Bool, M) ->
>> >> >     A = spawn(fun() -> a() end),
>> >> >     B = spawn(fun() -> b(A, Bool) end),
>> >> >     C = spawn(fun() -> c(B, M) end),
>> >> >     sleep(1000),
>> >> >     status(b, B),
>> >> >     status(c, C).
>> >> >
>> >> >
>> >> > a() ->
>> >> >     process_flag(trap_exit, true),
>> >> >     wait(a).
>> >> >
>> >> > b(A, Bool) ->
>> >> >     process_flag(trap_exit, Bool),
>> >> >     link(A),
>> >> >     wait(b).
>> >> >
>> >> > c(B, M) ->
>> >> >     link(B),
>> >> >     case M of
>> >> >     {die, Reason} ->
>> >> >         exit(Reason);
>> >> >     {divide, N} ->
>> >> >         1/N,
>> >> >         wait(c);
>> >> >     normal ->
>> >> >         true
>> >> >     end.
>> >> >
>> >> >
>> >> >
>> >> > wait(Prog) ->
>> >> >     receive
>> >> >     Any ->
>> >> >         io:format("Process ~p received ~p~n",[Prog, Any]),
>> >> >         wait(Prog)
>> >> >     end.
>> >> >
>> >> >
>> >> >
>> >> > sleep(T) ->
>> >> >     receive
>> >> >     after T -> true
>> >> >     end.
>> >> >
>> >> > status(Name, Pid) ->
>> >> >     case erlang:is_process_alive(Pid) of
>> >> >     true ->
>> >> >         io:format("process ~p (~p) is alive~n", [Name, Pid]);
>> >> >     false ->
>> >> >         io:format("process ~p (~p) is dead~n", [Name,Pid])
>> >> >     end.
>> >> >
>> >> >
>> >>
>> >> Ulf Wiger, CTO, Erlang Solutions, Ltd.
>> >> http://erlang-solutions.com
>> >
>> > ________________________________________________________________
>> > erlang-questions (at) erlang.org mailing list.
>> > See http://www.erlang.org/faq.html
>> > To unsubscribe; mailto:erlang-questions-unsubscribe@REDACTED
>> >
>> >
>>
>>
>>
>> --
>> --Hynek (Pichi) Vychodil
>>
>> Analyze your data in minutes. Share your insights instantly. Thrill
>> your boss.  Be a data hero!
>> Try GoodData now for free: www.gooddata.com
>



-- 
--Hynek (Pichi) Vychodil

Analyze your data in minutes. Share your insights instantly. Thrill
your boss.  Be a data hero!
Try GoodData now for free: www.gooddata.com


More information about the erlang-questions mailing list