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

Kresten Krab Thorup krab@REDACTED
Thu Aug 12 13:42:00 CEST 2010


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:erlang-questions-unsubscribe@REDACTED
> 

Kresten Krab Thorup, CTO, Trifork



More information about the erlang-questions mailing list