signal handling an mllex based filter

View: New views
3 Messages — Rating Filter:   Alert me  

signal handling an mllex based filter

by Michael Norrish :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

I have a filter that reads from stdin and writes to stdout.  The input
is lexed with an mllex program that recognises the tokens and outputs
the necessary transformations.

In other words, the end of the program looks like

  val lexer = filter.makeLexer (read_from_stream instream) state
  val _ = lexer()

I want the user to be able to hit control-c to reset the state of the
lexer.  In particular, if the lexer can get into different internal
states if it's in the middle of recognising a quotation literal
(something with delimiters).

It has MLlex code like

   <START>{quote-begin} (YYBEGIN INQUOTE; continue());
   ...

   <INQUOTE>{quote-end} (YYBEGIN START; continue());
   <INQUOTE>...

In Moscow ML, I did some magic to get SIGINT recognised as an Interrupt
exception, and did

   lexer() handle Interrupt => lexer()

In Poly/ML, I had to do a little different magic, but was again able to
get SIGINT recognised as an Interrupt exception.  I thus had the same
code again.

In MLton, I'm confused.

I can handle SIGINT with MLton.Signal.setHandler, but it seems as if I
am going to have to explicitly set myself up with a master thread that
repeatedly creates slave threads to run lexer().  Then in the handler, I
can just switch to the master, leaving the interrupted slave to expire
through lack of attention.

Is this stylistically and pragmatically correct?

Thanks,
Michael

_______________________________________________
MLton-user mailing list
MLton-user@...
http://mlton.org/mailman/listinfo/mlton-user

Re: signal handling an mllex based filter

by Wesley W. Terpstra :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Tue, Aug 4, 2009 at 7:47 AM, Michael Norrish <Michael.Norrish@...> wrote:
In Moscow ML, I did some magic to get SIGINT recognised as an Interrupt exception, and did
 lexer() handle Interrupt => lexer()

In MLton, I'm confused.

I can handle SIGINT with MLton.Signal.setHandler, but it seems as if I am going to have to explicitly set myself up with a master thread that repeatedly creates slave threads to run lexer().  Then in the handler, I can just switch to the master, leaving the interrupted slave to expire through lack of attention.

Sounds like a reasonable approach. There is no way to raise an exception in one thread from another, so you cannot interrupt the running lexer.


_______________________________________________
MLton-user mailing list
MLton-user@...
http://mlton.org/mailman/listinfo/mlton-user

Re: signal handling an mllex based filter

by Michael Norrish :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Wesley W. Terpstra wrote:

> Sounds like a reasonable approach. There is no way to raise an
> exception in one thread from another, so you cannot interrupt the
> running lexer.

Right.  (Poly/ML provides a command to raise Interrupt in all running
threads, so that's what I did there.  It's a nice convenience.)

Anyway, the approach did work, which was gratifying.

For the sake of posterity, there is one error in what I wrote
initially. I claimed that it was enough to do

     val lexer = filter.makeLexer (read_from_stream instream) state

and then repeatedly call

     lexer()

after interruptions.  In fact, the call to makeLexer sets up a MLLex
generated lexer and initialises the internal state variable, so when
you are switching to a fresh slave you need to call

   filter.makeLexer ...

again, rather than just lexer().  Otherwise, you will just inherit the
old internal state.

Also, there is no need for a separate master thread: the handler can
just create fresh slaves and switch to them directly.  My code now
looks like:

----------------------------------------------------------------------

...

fun slave() = let
   val lexer = filter.makeLexer (read_from_stream instream) state
in
   lexer();
   TextIO.closeOut outstream;
   exit success
end

open MLton.Thread

fun interrupt_handler _ = let
   open filter.UserDeclarations
in
   ... reset state's reference variables ...
   prepare (new slave, ())
end

val h = MLton.Signal.Handler.handler interrupt_handler
val _ = MLton.Signal.setHandler(Posix.Signal.int, h)

val _ = switch (fn _ => prepare (new slave, ()))
----------------------------------------------------------------------

The thread-specific code is nice and short.

Best,
Michael.

_______________________________________________
MLton-user mailing list
MLton-user@...
http://mlton.org/mailman/listinfo/mlton-user