[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