caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* Callbacks from C to OCaml
@ 2009-07-10 11:16 David Allsopp
  2009-07-11  7:54 ` [Caml-list] " ygrek
  0 siblings, 1 reply; 3+ messages in thread
From: David Allsopp @ 2009-07-10 11:16 UTC (permalink / raw)
  To: OCaml List

I'm having some trouble with a library wrapping Windows Services - I'm
wondering if anyone can shed some light on possible pitfalls with the
mechanism for C callbacks while I continue to scratch my head! Although my
problem is with a Windows-based solution my overall question is about
C-callbacks interacting with OCaml so please don't be put off by the Win32
aspect of it :o)

The overall layout is this: the main program is OCaml (i.e. it's an OCaml
program using C-stubs rather than a C-program calling OCaml). The flow of
execution is as follows:

The OCaml program invokes a C-stub which calls the Win32 API function
StartServiceCtrlDespatcher which, amongst other things, takes a pointer to a
C function called ServiceMain. This pointer will be invoked during
StartServiceCtrlDespatcher (synchronously - StartServiceCtrlDespatcher does
not return until the service is stopped) and carries out the following
tasks:

1. It registers a C function with the Windows Service Control Manager (SCM)
called ServiceCtrlHandler which the SCM may callback to *at any time*
2. It does some housekeeping to initialise the service which includes a
call-back to an OCaml function registered by the initial C-stub
3. Assuming success, a call-back is made to another OCaml function. This may
block or it may return immediately.
4. ServiceMain then waits on an event which will only be signalled when the
SCM instructs the service to stop (because ServiceMain is not supposed to
terminate until instructed to). The call to this code is wrapped with
caml_enter_blocking_section and caml_leave_blocking_section (but note that a
particular service may choose to block in the OCaml-land function called in
step 3 instead - the event is just in place to ensure that this is the case)

Now, at any time, the SCM may invoke the ServiceCtrlHandler function
registered with it. This also needs to callback to an OCaml function to work
out what to do (the closure was registered in the initial call).

What happens at this point with regard to OCaml's global lock and being in
the correct threading context? I must confess that I don't fully understand
how the callback works at all in the single-threaded context - presumably
when SCM calls the function, it simply executes code in its own thread
context (so it can presumably introduce a form of multi-threading to a
program which isn't expecting it?).

Should ServiceCtrlHandler (which is only ever invoked from Windows - i.e.
from C-land) be wrapped in the reverse of a blocking construct... i.e.

void WINAPI ServiceCtrlHandler(DWORD Opcode) {
  CAMLparam0(); // The function does allocate...

  caml_leave_blocking_section();

  /* code including caml_callback and caml_alloc_tuple calls */

  caml_enter_blocking_section();

  CAMLreturn0();
}

Can the *_blocking_section functions be used in this way or is there
something else which should be done? My current implementation is flaky - it
works for some services and not for others (and it's very unreliable when
compiled with threading enabled - my current implementation actually cheats
and provides a single-threaded stub application which communicates with a
threaded application via standard input and output to avoid this problem)
which leads to me think that the services which work are probably lucky on
the allocation front and so get away with it and the others essentially
corrupt the runtime and segfault.

Any pointers much appreciated - the manual on C stubs doesn't even mention
the caml_enter_blocking_section/caml_leave_blocking_section functions so
it's sort of a difficult area on which to get information. I'm at this stage
definitely more convinced that it's an error somewhere in my code rather
than the OCaml runtime :o)

Are there any other libraries which contains C stubs handling callbacks in a
similar fashion which I could look at?

Many thanks,


David


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [Caml-list] Callbacks from C to OCaml
  2009-07-10 11:16 Callbacks from C to OCaml David Allsopp
@ 2009-07-11  7:54 ` ygrek
  2009-07-11 11:39   ` David Allsopp
  0 siblings, 1 reply; 3+ messages in thread
From: ygrek @ 2009-07-11  7:54 UTC (permalink / raw)
  To: caml-list

[-- Attachment #1: Type: text/plain, Size: 1135 bytes --]

On Fri, 10 Jul 2009 12:16:17 +0100
"David Allsopp" <dra-news@metastack.com> wrote:

> Now, at any time, the SCM may invoke the ServiceCtrlHandler function
> registered with it. This also needs to callback to an OCaml function to work
> out what to do (the closure was registered in the initial call).
> 
> What happens at this point with regard to OCaml's global lock and being in
> the correct threading context? I must confess that I don't fully understand
> how the callback works at all in the single-threaded context - presumably
> when SCM calls the function, it simply executes code in its own thread
> context (so it can presumably introduce a form of multi-threading to a
> program which isn't expecting it?).

Yes, SCM creates new thread for the callback.
And this thread is not registered with OCaml runtime, and so
you can't do any allocation on it. I used windows services in the same setup and  
just set a boolean flag when SCM signalled service to stop, while periodically checking
this flag in ocaml thread..

See also http://caml.inria.fr/mantis/view.php?id=4702

Hope it helps.

-- 
 ygrek

[-- Attachment #2: Type: application/pgp-signature, Size: 197 bytes --]

^ permalink raw reply	[flat|nested] 3+ messages in thread

* RE: [Caml-list] Callbacks from C to OCaml
  2009-07-11  7:54 ` [Caml-list] " ygrek
@ 2009-07-11 11:39   ` David Allsopp
  0 siblings, 0 replies; 3+ messages in thread
From: David Allsopp @ 2009-07-11 11:39 UTC (permalink / raw)
  To: caml-list

ygrek wrote:
> On Fri, 10 Jul 2009 12:16:17 +0100
> "David Allsopp" <dra-news@metastack.com> wrote:
> 
> > Now, at any time, the SCM may invoke the ServiceCtrlHandler function
> > registered with it. This also needs to callback to an OCaml function
> > to work out what to do (the closure was registered in the initial call).
> >
> > What happens at this point with regard to OCaml's global lock and
> > being in the correct threading context? I must confess that I don't
> > fully understand how the callback works at all in the single-threaded
> > context - presumably when SCM calls the function, it simply executes
> > code in its own thread context (so it can presumably introduce a form
> > of multi-threading to a program which isn't expecting it?).
> 
> Yes, SCM creates new thread for the callback.

That's handy to know - I was going to do some further experimentation in C
to check that so that hassle is saved, thanks!

> And this thread is not registered with OCaml runtime, and so you can't
> do any allocation on it. I used windows services in the same setup and
> just set a boolean flag when SCM signalled service to stop, while
> periodically checking this flag in ocaml thread..

Following this, and an off-list exchange with Philippe Wang, I'd arrived at
the same conclusion. I'd tried to model the whole procedure essentially on
how'd you'd write it in C with callbacks and that was clearly the wrong
decision!

> See also http://caml.inria.fr/mantis/view.php?id=4702

Presumably if this patch is eventually incorporated, that would allow the C
version of ServiceCtrlHandler to register its thread with the OCaml runtime
and therefore safely callback into OCaml code? I shall watch the issue -
although having to create a couple of message-passing helper threads to
accomplish this task is hardly going to slow anything down.

> Hope it helps.

Thank you! It's good to know for definite that I've been barking up the
wrong tree - especially as it tantalising almost worked.


David



^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2009-07-11 11:39 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-07-10 11:16 Callbacks from C to OCaml David Allsopp
2009-07-11  7:54 ` [Caml-list] " ygrek
2009-07-11 11:39   ` David Allsopp

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).