[erlang-questions] Unidirectional linking?

Igor Ribeiro Sucupira igorrs@REDACTED
Wed May 25 10:50:40 CEST 2011


Parent will probably need to do more work after it gets the result
from Child, so, in the end, you would need to restore trap_exit to
false (unless it wasn't false before) and then call receive again, to
make sure there weren't other exit messages while trap_exit was true.

That's what worries me about the trap_exit solution: the more code you
need, the more conditions you may be forgetting to consider.

I am planning to put that logic inside of a "general" function
(something like catch_apply(Module, Function, Args, Timeout)) and use
it in my system (that handles hundreds of requests per second).
It may happen, for example, that Op1 calls OpA and OpB, while Op2
calls OpC and OpA, with Op1 and Op2 having different timeouts. So, it
may get very wild and, having some experience with that kind of load,
I have seen in practice that race conditions are very real.

In the first use case I'm planning, leaking Child or having Parent
dying (or not dying) by mistake sometimes might not be so bad. But one
day other people may begin to use the function for other operations
and I don't want anybody hurt.  :)

Thanks!
Igor.

--
"The secret of joy in work is contained in one word - excellence. To
know how to do something well is to enjoy it." - Pearl S. Buck.


On Wed, May 25, 2011 at 4:28 AM, Mazen Harake <mazen.harake@REDACTED> wrote:
> Perhaps something like this:
>
> process_flag(trap_exit, true),
> Parent = self(),
> Child = spawn_link(fun() -> Parent ! (catch Op) end),
> receive
>   {'EXIT', ParentsParent, Reason} ->
>     exit(Reason);
>   Result ->
>     Result
>  after N ->
>     unlink(Child),
>     exit(Child, timeout),
>     timeout
> end.
>
> if you get an exit signal from the parent's parent you will exit if you are
> in the receive clause and you will ignore it (unless it is a kill) if you
> are in between the unlink and exit child?
>
> I do however still think that this is very defensive and that the
> probability of getting an exit between unlink and exit is very small unless
> the timeout in N is exactly the same (very very close to) the timeout that
> the parent's parent has for exiting the parent.
>
>
>
> On 25 May 2011 08:51, Igor Ribeiro Sucupira <igorrs@REDACTED> wrote:
>>
>> Supposing someone used the same logic (with timeout/kill) to spawn the
>> parent process, the parent could be killed at any moment (but yeah: it
>> would be bad luck to have that happening right after it called
>> unlink).
>>
>> Thanks.
>> Igor.
>>
>> On Wed, May 25, 2011 at 3:20 AM, Mazen Harake <mazen.harake@REDACTED>
>> wrote:
>> > Why would someone "kill the parent"? Do you have processes which are
>> > randomly choosing other processes to terminate? ;)
>> >
>> > If your answer is "No" then I would suggest that you just kill the
>> > worker
>> > processes that is taking to long, kill it in cold blood, imo.
>> >
>> > There is no reason to think about too many "if"-scenarios when the
>> > scenarios
>> > are too far fetched. Try the simple version first :)
>> >
>> > otherwise you can either trap_exits or use monitors instead.
>> >
>> > /M
>> >
>> > On 25 May 2011 08:00, Igor Ribeiro Sucupira <igorrs@REDACTED> wrote:
>> >>
>> >> Suppose there is a heavy operation Op that in some cases takes so long
>> >> to finish that the caller loses interest in the result and gives up.
>> >>
>> >> I want to perform that operation in a way that allows me to:
>> >> 1) Interrupt its execution if it does not finish in N milliseconds.
>> >> 2) Interrupt its execution if the calling process exits (here I'm
>> >> already supposing Op has to be run in another Erlang process, due to
>> >> goal 1).
>> >>
>> >> To implement that, it seems unidirectional linking would be needed. Is
>> >> there another safe and convenient way to do it?
>> >>
>> >> The first idea I had was something like this:
>> >>
>> >> Parent = self(),
>> >> Child = spawn_link(fun() -> Parent ! (catch Op) end),
>> >> receive Result -> Result
>> >> after N -> unlink(Child), exit(Child, timeout), timeout
>> >> end.
>> >>
>> >> But, if Parent is killed by another process right after calling
>> >> unlink, Child would be left executing.
>> >> Another problem is that I don't want Parent to die if Child exits for
>> >> non-timeout reasons (although it seems very unlikely in the code
>> >> above, with the catch).
>> >>
>> >> I was now thinking of substituting unlink(Child) with
>> >> process_flag(trap_exit, true) and then kill Child, receive its exit
>> >> message, set trap_exit to false again (I'm assuming it was false), and
>> >> finally check if there were other exit messages (suiciding if it was
>> >> the case).
>> >>
>> >> But then the code would become too ugly, so I got lazy and decided to
>> >> post to this list.  :-)
>> >>
>> >> What do you think?
>> >>
>> >> Thanks.
>> >> Igor.
>> >> _______________________________________________
>> >> erlang-questions mailing list
>> >> erlang-questions@REDACTED
>> >> http://erlang.org/mailman/listinfo/erlang-questions
>> >
>> >
>
>



More information about the erlang-questions mailing list