
Recently I've been hacking together a small Haskell module on top of ptrace(2). It's comming along nicely, but it's very low level. The signals arrive in a list: wait :: Int -> IO [Signal] and processing of the signals can be done using e.g. mapM_: wait childPid >>= mapM_ processSignal In a few cases this low level requires quite a bit of extra code. Code needs to be repeated in every program using the module. Dealing with breakpoints is a good example: - Setting a breakpoint requires storing the old instruction at the address - When hitting a breakpoint the old instruction should be put back, EIP backed up, perform one single-step, and last put the breakpoint back again. I believe adding another layer on top of what I have now seems like a good idea. AFAICS that means having a state (I must keep track of the original instruction). That can easily be done by wrapping IO in a StateT: forEachSignal:: Int -> (Signal -> IO ()) -> StateT DbgEnv IO () forEachSignal childPid procSignal = ... (Or would it be better using IORefs and "OO" in the way described in "IO Inside"[1]?) What I am struggling with is how to allow the user of the module to have state as well. I can see how "OO"[1] can be used to solve it, but is there a more elegant, maybe more idiomatic (Haskellic??), way? Or am I missing a more elegant way of dealing with this? /M [1]: http://haskell.org/haskellwiki/IO_inside#Example:_emulating_OOP_with_record_... -- Magnus Therning (OpenPGP: 0xAB4DFBA4) magnus@therning.org Jabber: magnus.therning@gmail.com http://therning.org/magnus

On Wed, Mar 21, 2007 at 09:28:15AM +0000, Magnus Therning wrote:
Recently I've been hacking together a small Haskell module on top of ptrace(2). It's comming along nicely, but it's very low level. The signals arrive in a list:
wait :: Int -> IO [Signal]
Aside: Why lazy? It seems like wait :: Int -> IO Signal would be better, and almost as easy to use: sequence_ . repeat $ wait >>= processSignal
and processing of the signals can be done using e.g. mapM_:
wait childPid >>= mapM_ processSignal
[snip]
(Or would it be better using IORefs and "OO" in the way described in "IO Inside"[1]?)
What I am struggling with is how to allow the user of the module to have state as well. I can see how "OO"[1] can be used to solve it, but is there a more elegant, maybe more idiomatic (Haskellic??), way?
In some sense a PID is *already* a handle to external mutable state, so the original motivation for IORefs applies. data Child = Child { pid :: CInt, debug_state :: IORef StateBlock } wait :: Child -> IO () ... HTH, Stefan

On Wed, Mar 21, 2007 at 07:19:20 -0700, Stefan O'Rear wrote:
On Wed, Mar 21, 2007 at 09:28:15AM +0000, Magnus Therning wrote:
Recently I've been hacking together a small Haskell module on top of ptrace(2). It's comming along nicely, but it's very low level. The signals arrive in a list:
wait :: Int -> IO [Signal]
Aside: Why lazy? It seems like
wait :: Int -> IO Signal
would be better, and almost as easy to use:
sequence_ . repeat $ wait >>= processSignal
If I do it lazy then I can end the list when a "terminating signal" arrives (e.g. on interrupt). AFAICS the only option when using an infinate list is to throw an error. (Am I right about this?) One could argue that I need to deal with errors anyway so what you suggest might turn out to be more elegant in the end. (Another cute thing is that your suggestion removes the need to use unsafeInterleaveIO. See [1] for that discussion.)
and processing of the signals can be done using e.g. mapM_:
wait childPid >>= mapM_ processSignal
[snip]
(Or would it be better using IORefs and "OO" in the way described in "IO Inside"[1]?)
What I am struggling with is how to allow the user of the module to have state as well. I can see how "OO"[1] can be used to solve it, but is there a more elegant, maybe more idiomatic (Haskellic??), way?
In some sense a PID is *already* a handle to external mutable state, so the original motivation for IORefs applies.
data Child = Child { pid :: CInt, debug_state :: IORef StateBlock }
wait :: Child -> IO ()
Yes, good point. Thanks. /M [1]: http://www.haskell.org/pipermail/haskell-cafe/2007-January/021367.html -- Magnus Therning (OpenPGP: 0xAB4DFBA4) magnus@therning.org Jabber: magnus.therning@gmail.com http://therning.org/magnus
participants (2)
-
Magnus Therning
-
Stefan O'Rear