[erlang-questions] Best way to kill an async thread in a linked in driver?

Nicholas Frechette <>
Fri Aug 13 02:29:23 CEST 2010


It is pretty standard to pool for a shared variable and exit/clean up on
state change. I've done this hundred of times.
Alternatively, you might be able to flag that thread as a daemon thread.
Typically programs exit when only daemon threads remain and all non-daemon
threads have completed/exited. I know they have that with C++ on solaris,
java, python, etc. Not sure about your specifics though but worth checking
it out.

You can play with the timeout value of your polling. High values mean that
you'll be penalized when exiting but you'll be decreasing the delay in
reading while lower values will do the opposite. Just find a decent balance
for your app but afaik, few people have problems waiting 1-2s for an app to
exit.
Nicholas

On Thu, Aug 12, 2010 at 6:21 PM, Mazen Harake <
> wrote:

>  Sorry, I should have been a bit more clear:
> I need to do things in Erlang space while I'm waiting for input, such as
> telling the driver to print out a character at pos y,x.
>
> This is the reason I can't be blocked in the driver.
>
> Still... I may have missed something, you are more than welcome to
> enlighten me :):)
>
> /M
>
>
> On 13/08/2010 01:14, Mazen Harake wrote:
>
>>  Hmm... I'm not sure what you mean but the part I do understand is that
>> select() blocks... right? I can't have anything that blocks in the driver
>> since I must be able to interact with it as I'm waiting for input. E.g. I
>> need to update a certain part of the screen even if the user is not pressing
>> any buttons.
>>
>> I don't see how select() would make any difference? Perhaps I
>> misunderstood you, could you explain a bit more on how that would work? Or
>> perhaps point me to some direction?
>>
>> Thanks for feedback,
>>
>> /M
>>
>> On 12/08/2010 14:42, Kresten Krab Thorup wrote:
>>
>>> I'd write the driver using select and non-blocking reads; that way you
>>> would not need async threads at all.
>>>
>>> Kresten
>>>
>>> On Aug 12, 2010, at 10:31 , Mazen Harake wrote:
>>>
>>>   It was late yesterday and despite 2 coffees and a nice breakfast I
>>>> still can't solve this one. Maybe a nudge in the right direction anyone?
>>>>
>>>> Scenario:
>>>> I have a linked in driver; cecho [1], when ever I want to read input I
>>>> disable input to Erlang (-noinput) and use the getch() function in C
>>>> instead (never mind why ;)). This function is run in a seperate async
>>>> thread using driver_async() [2][3], and blocks at getch(). When a
>>>> character is read it sends a message back to Erlang (driver_output())
>>>> and then the thread exits, when the message comes back to Erlang the
>>>> character is sent to the requester and the thread is restarted (which
>>>> again blocks at getch()).
>>>>
>>>> Later if I do an erlang:halt(0) ("graceful halt") the thread is still
>>>> lingering despite having closed the port[4] (which, Afaik should close
>>>> the thread as well) but it seems stay alive somehow. erlang:halt(1) kill
>>>> it immediately so it is not a problem.
>>>>
>>>> Questions:
>>>> 1) Is my "analysis" correct? Is this infact what is happening? Anyone
>>>> who can explain this behaviour (I.e. why it lingers on)?
>>>>
>>>> 2) If Question 1 then; what is the best way to kill the thread when I
>>>> exit? driver_async_cancel() only works for threads that are not
>>>> executing (according to Documentation) so what to do? I did an ugly
>>>> workaround which sets a global flag and then I timeout the getch()
>>>> operation and read for ERR. If I get an ERR I just read the abort flag
>>>> and if it is set I just die otherwise I try to getch() again. This
>>>> avoids hanging around for more then a tenth of a second but it is pretty
>>>> ugly in my oppinion and I'm forced to go into halfdelay mode which means
>>>> I can not allow this option outside of the driver because I become
>>>> dependent on it. I'd rather do it the "right way" if there is such a
>>>> way.
>>>>
>>>> References: (Links given as commit Ids so that if someone searches then
>>>> they get relevant code and not the latest)
>>>> [1]
>>>>
>>>> http://github.com/mazenharake/cecho/tree/199fd342ba186e1154c32dbfdcf2d9222e25f9f4
>>>>
>>>> [2]
>>>>
>>>> http://github.com/mazenharake/cecho/blob/199fd342ba186e1154c32dbfdcf2d9222e25f9f4/c_src/cecho.c#L119
>>>>     static void request(ErlDrvData drvstate, char *buf, int buflen) {
>>>> state *st = (state *)drvstate;
>>>> driver_async(st->drv_port, NULL, loop_getch, (void *)st, NULL);
>>>>     }
>>>>
>>>> [3]
>>>>
>>>> http://github.com/mazenharake/cecho/blob/199fd342ba186e1154c32dbfdcf2d9222e25f9f4/c_src/cecho.c#L557
>>>> void loop_getch(void *arg) {
>>>>     state *st = (state *)arg;
>>>>     ei_x_buff eixb;
>>>>     int keycode;
>>>>     ei_x_new_with_version(&eixb);
>>>>     keycode = getch();
>>>>     integer(&eixb, keycode);
>>>>     driver_output(st->drv_port, eixb.buff, eixb.index);
>>>> }
>>>>
>>>> [4]
>>>>
>>>> http://github.com/mazenharake/cecho/blob/199fd342ba186e1154c32dbfdcf2d9222e25f9f4/src/cecho_srv.erl#L76
>>>> terminate(_Reason, State) ->
>>>>     do_call(State#state.port, ?ENDWIN),
>>>>     do_call(State#state.port, ?CURS_SET, ?ceCURS_NORMAL),
>>>>     erlang:port_close(State#state.port),
>>>>     erl_ddll:unload("cecho").
>>>>
>>>>
>>>> ________________________________________________________________
>>>> erlang-questions (at) erlang.org mailing list.
>>>> See http://www.erlang.org/faq.html
>>>> To unsubscribe; mailto:
>>>>
>>>>  Kresten Krab Thorup, CTO, Trifork
>>>
>>>
>>
>> ________________________________________________________________
>> erlang-questions (at) erlang.org mailing list.
>> See http://www.erlang.org/faq.html
>> To unsubscribe; mailto:
>>
>>
>
> ________________________________________________________________
> erlang-questions (at) erlang.org mailing list.
> See http://www.erlang.org/faq.html
> To unsubscribe; mailto:
>
>


More information about the erlang-questions mailing list