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

Mazen Harake <>
Fri Aug 13 18:25:26 CEST 2010

  You're actually spot on about the timeout "tuning", I was playing with 
that yesterday and my conclusion was (I read up on it a little) that 
most people aren't able to tell the small differences in delays that can 
occur between pressing a key and reacting to it.

Anyway I did implement this version now and I'm going to try out the 
driver_select() version later to compare in terms of user-experience and 
complexity of the code. If the driver_select() version works out as well 
as the version I have now (not yet pushed to branch) I might go with that.

Thanks for the feedback!


On 13/08/2010 03:29, Nicholas Frechette wrote:
> 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 
> < 
> <mailto:>> 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 <http://erlang.org>
>                 mailing list.
>                 See http://www.erlang.org/faq.html
>                 To unsubscribe;
>                 mailto:
>                 <mailto:>
>             Kresten Krab Thorup, CTO, Trifork
>         ________________________________________________________________
>         erlang-questions (at) erlang.org <http://erlang.org> mailing list.
>         See http://www.erlang.org/faq.html
>         To unsubscribe; mailto:
>         <mailto:>
>     ________________________________________________________________
>     erlang-questions (at) erlang.org <http://erlang.org> mailing list.
>     See http://www.erlang.org/faq.html
>     To unsubscribe; mailto:
>     <mailto:>

More information about the erlang-questions mailing list