Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

[Caml-list] Ocaml debugger under Windows

38 views
Skip to first unread message

Dmitry Bely

unread,
Feb 5, 2008, 4:46:59 AM2/5/08
to ocaml
The topic has a long history [1], but since then nothing has actually
changed. It's easy to understand: INRIA people are busy and there are
probably quite few Ocaml users in the Windows land to worry about. So I
decided to do something myself :) (as it was with mingw port several years
ago).

Let's go into detail. Ocam debugger consists of the the two parts: the
client (byterun/debugger.c linked into debuggee) and the server
(ocamldebug). The following issues should be addressed to make a Windows
port:

1. Checkpointing is done via Unix fork() (client)

The most problematic one. I have spend a fair amount of time trying to find
an acceptable solution.
a) direct port of fork() to Windows. There is a BSD-licenced Windows fork()
in tcsh sources [2] that could be used. It's based on Cygwin ideas. But how
to handle dynamically loaded DLLs (loaded via LoadLibrary())? I asked the
author (Amol Deshpande) and he replied:

"DLLs that are dynamically loaded are a can of worms. I would not support
those if I were you."

BTW, does Cygwin do this right? I doubt at least.

b) some checkpoint library. Although Web search gives many references, e.g.
[3], I have not found yet anything ready-to-use, even commercial!

2. Unix select (server)

It is a problem because server waits for network and console events
simultaneously. To work on Windows the main loop should probably be
multi-threaded.

3. Unix sockets (client & server)

Probably can be ignored. Internet sockets are quite enough.

So what is done now.

- Client

It's ported without (1) and (3). To me it's quite usable even without
checkpoints.

- Server

I don't bother to do (2) right now (until the whole idea is accepted).
Currently I use cygwin-compiled ocamldebug with checkpoints and Unix sockets
disabled by default. It works well with the native Win32 clients.

- OcaIDE

Yes, with minor changes in OcaIDE the debugged works there.

If it's interesting for anyone I can publish a patch against Ocaml 3.10.1

- Dmitry Bely

[1]
http://caml.inria.fr/pub/ml-archives/caml-list/1999/03/f44178e212e78826bcbdee52ddf6fd91.en.html
http://caml.inria.fr/pub/ml-archives/caml-list/2002/10/ed776d7376ed7a9676d4a9981372ccdf.fr.html

[2] http://www.tcsh.org/MostRecentRelease

[3]
http://www.usenix.org/publications/library/proceedings/usenix-nt98/full_papers/srouji/srouji_html/srouji.html

Alain Frisch

unread,
Feb 5, 2008, 4:55:07 AM2/5/08
to Dmitry Bely, ocaml
Dmitry Bely wrote:
> The topic has a long history [1], but since then nothing has actually
> changed. It's easy to understand: INRIA people are busy and there are
> probably quite few Ocaml users in the Windows land to worry about. So I
> decided to do something myself :) (as it was with mingw port several
> years ago).
>...

> If it's interesting for anyone I can publish a patch against Ocaml 3.10.1

Yes, that's definitely interesting for us!

Is there any hope to build the server with the mingw or msvc port?

-- Alain

_______________________________________________
Caml-list mailing list. Subscription management:
http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
Archives: http://caml.inria.fr
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs

Dmitry Bely

unread,
Feb 5, 2008, 12:31:41 PM2/5/08
to Alain Frisch, ocaml
On Feb 5, 2008 12:54 PM, Alain Frisch <al...@frisch.fr> wrote:
> Dmitry Bely wrote:
> > The topic has a long history [1], but since then nothing has actually
> > changed. It's easy to understand: INRIA people are busy and there are
> > probably quite few Ocaml users in the Windows land to worry about. So I
> > decided to do something myself :) (as it was with mingw port several
> > years ago).
> >...
> > If it's interesting for anyone I can publish a patch against Ocaml 3.10.1
>
> Yes, that's definitely interesting for us!
>
> Is there any hope to build the server with the mingw or msvc port?

As soon as the following function is rewritten:

debugger/input_handling.ml

(* Handle active files until `continue_main_loop' is false. *)
let main_loop () =
let old_state = !continue_main_loop in
try
continue_main_loop := true;
while !continue_main_loop do
try
let (input, _, _) =
select (List.map fst !active_files) [] [] (-1.)
in
List.iter
(function fd ->
let (funct, iochan) = (List.assoc fd !active_files) in
funct iochan)
input
with
Unix_error (EINTR, _, _) -> ()
done;
continue_main_loop := old_state
with
x ->
continue_main_loop := old_state;
raise x

here Unix.select() waits for both network and user input events. We
could split this into 2 threads, but how to interrupt network select()
when we going to exit? Well, we could use some small timeout value for
select() (say 500ms) and restart it the loop when !continue_main_loop
is set, but this looks not very elegant... Or it's OK?

The point is not to modify win32unix library or write Win32-specific C
functions for ocamldebug. I believe it's necessary to be ever accepted
by INRIA.


- Dmitry Bely

Benedikt Grundmann

unread,
Feb 5, 2008, 12:41:40 PM2/5/08
to Dmitry Bely, ocaml, Alain Frisch
Use Shawn Wagner's MsgQueue module to communicate between both threads
in a select friendly way.

http://raevnos.pennmush.org/code/ethread/doc/MsgQueue.html

Cheers,

Bene

2008/2/5, Dmitry Bely <dmitr...@gmail.com>:


--
Calvin: I try to make everyone's day a little more
surreal.

(From Calvin & Hobbes)

Alain Frisch

unread,
Feb 5, 2008, 4:06:18 PM2/5/08
to Dmitry Bely, caml-list
Dmitry Bely wrote:
> I don't think it would work on Windows. You cannot select() on
> arbitrary Unix.file_descr - only socket-associated descriptor can be
> used.

Do you know how Cygwin emulate the desired behavior? Does it use threads?

-- Alain

Dmitry Bely

unread,
Feb 6, 2008, 3:57:10 AM2/6/08
to Alain Frisch, ocaml
On Feb 6, 2008 12:00 AM, Alain Frisch <al...@frisch.fr> wrote:
> > I don't think it would work on Windows. You cannot select() on
> > arbitrary Unix.file_descr - only socket-associated descriptor can be
> > used.
>
> Do you know how Cygwin emulate the desired behavior? Does it use threads?

It surely use WaitForMultipleObjects() instead of select(). The
implementation is quite complicated; GDB's one seems to be better
showing an idea (see below).

But frankly speaking I don't like to add any C code here - in fact it
means altering win32unix library that is unlikely to happen. Can it be
solved on Caml level? Anyone? Is select() with small timeout is
acceptable?

/* Wrapper for select. On Windows systems, where the select interface
only works for sockets, this uses the GDB serial abstraction to
handle sockets, consoles, pipes, and serial ports.

The arguments to this function are the same as the traditional
arguments to select on POSIX platforms. */

int
gdb_select (int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
struct timeval *timeout)
{
static HANDLE never_handle;
HANDLE handles[MAXIMUM_WAIT_OBJECTS];
HANDLE h;
DWORD event;
DWORD num_handles;
int fd;
int num_ready;
int indx;

num_ready = 0;
num_handles = 0;
for (fd = 0; fd < n; ++fd)
{
HANDLE read = NULL, except = NULL;
struct serial *scb;

/* There is no support yet for WRITEFDS. At present, this isn't
used by GDB -- but we do not want to silently ignore WRITEFDS
if something starts using it. */
gdb_assert (!writefds || !FD_ISSET (fd, writefds));

if ((!readfds || !FD_ISSET (fd, readfds))
&& (!exceptfds || !FD_ISSET (fd, exceptfds)))
continue;
h = (HANDLE) _get_osfhandle (fd);

scb = serial_for_fd (fd);
if (scb)
serial_wait_handle (scb, &read, &except);

if (read == NULL)
read = h;
if (except == NULL)
{
if (!never_handle)
never_handle = CreateEvent (0, FALSE, FALSE, 0);

except = never_handle;
}

if (readfds && FD_ISSET (fd, readfds))
{
gdb_assert (num_handles < MAXIMUM_WAIT_OBJECTS);
handles[num_handles++] = read;
}

if (exceptfds && FD_ISSET (fd, exceptfds))
{
gdb_assert (num_handles < MAXIMUM_WAIT_OBJECTS);
handles[num_handles++] = except;
}
}
/* If we don't need to wait for any handles, we are done. */
if (!num_handles)
{
if (timeout)
Sleep (timeout->tv_sec * 1000 + timeout->tv_usec / 1000);

return 0;
}

event = WaitForMultipleObjects (num_handles,
handles,
FALSE,
timeout
? (timeout->tv_sec * 1000
+ timeout->tv_usec / 1000)
: INFINITE);
/* EVENT can only be a value in the WAIT_ABANDONED_0 range if the
HANDLES included an abandoned mutex. Since GDB doesn't use
mutexes, that should never occur. */
gdb_assert (!(WAIT_ABANDONED_0 <= event
&& event < WAIT_ABANDONED_0 + num_handles));
if (event == WAIT_FAILED)
return -1;
if (event == WAIT_TIMEOUT)
return 0;
/* Run through the READFDS, clearing bits corresponding to descriptors
for which input is unavailable. */
h = handles[event - WAIT_OBJECT_0];
for (fd = 0, indx = 0; fd < n; ++fd)
{
HANDLE fd_h;
struct serial *scb;

if ((!readfds || !FD_ISSET (fd, readfds))
&& (!exceptfds || !FD_ISSET (fd, exceptfds)))
continue;

if (readfds && FD_ISSET (fd, readfds))
{
fd_h = handles[indx++];
/* This handle might be ready, even though it wasn't the handle
returned by WaitForMultipleObjects. */
if (fd_h != h && WaitForSingleObject (fd_h, 0) != WAIT_OBJECT_0)
FD_CLR (fd, readfds);
else
num_ready++;
}

if (exceptfds && FD_ISSET (fd, exceptfds))
{
fd_h = handles[indx++];
/* This handle might be ready, even though it wasn't the handle
returned by WaitForMultipleObjects. */
if (fd_h != h && WaitForSingleObject (fd_h, 0) != WAIT_OBJECT_0)
FD_CLR (fd, exceptfds);
else
num_ready++;
}

/* We created at least one event handle for this fd. Let the
device know we are finished with it. */
scb = serial_for_fd (fd);
if (scb)
serial_done_wait_handle (scb);
}

return num_ready;
}

- Dmitry Bely

Xavier Leroy

unread,
Feb 6, 2008, 12:13:24 PM2/6/08
to Dmitry Bely, ocaml, Alain Frisch
Hello Dmitry,

I'm delighted to see your attempts at getting ocamldebug to work under
Windows.

Generally speaking, the Windows port is the part of OCaml where we
most desperately need outside help, as (1) it consumes quite a bit of
my very limited time, (2) it's a cost center for the Caml development
team (none of us uses Windows for our research activities), and (3)
none of us is competent with Win32 programming.

(For example, if anyone could help debugging PR#4399, that would be
much appreciated.)

Coming back to ocamldebug:

> The point is not to modify win32unix library or write Win32-specific C
> functions for ocamldebug. I believe it's necessary to be ever accepted
> by INRIA.

Actually, I would be happy with a Win32 implementation of Unix.select
that works over any combination of sockets and file descriptors.
Unfortunately, it looks like we'd need a gross hack involving threads,
WaitForMultipleObjects() and select(), but if someone comes up with an
implementation that isn't too gross, I'll be interested.

- Xavier Leroy

Dmitry Bely

unread,
Feb 6, 2008, 1:23:26 PM2/6/08
to Xavier Leroy, ocaml, Alain Frisch
On Feb 6, 2008 8:12 PM, Xavier Leroy <Xavier...@inria.fr> wrote:
> Hello Dmitry,
>
> I'm delighted to see your attempts at getting ocamldebug to work under
> Windows.
>
> Generally speaking, the Windows port is the part of OCaml where we
> most desperately need outside help, as (1) it consumes quite a bit of
> my very limited time, (2) it's a cost center for the Caml development
> team (none of us uses Windows for our research activities), and (3)
> none of us is competent with Win32 programming.
>
> (For example, if anyone could help debugging PR#4399, that would be
> much appreciated.)

Alas, I have not migrated to Vista yet. But once the reporter has
Visual C++ experience I would recommend him to build OCaml from
sources with debug info enabled (if won't compile out-of-the-box but
the fix is trivial) and launch ocamlwin under debugger. When it should
become obvious where the access violation occurs.

> Coming back to ocamldebug:
>
> > The point is not to modify win32unix library or write Win32-specific C
> > functions for ocamldebug. I believe it's necessary to be ever accepted
> > by INRIA.
>
> Actually, I would be happy with a Win32 implementation of Unix.select
> that works over any combination of sockets and file descriptors.
> Unfortunately, it looks like we'd need a gross hack involving threads,
> WaitForMultipleObjects() and select(), but if someone comes up with an
> implementation that isn't too gross, I'll be interested.

Indeed, porting select() to Windows would be preferable.
WaitForMultipleObjects() can wait for console, pipe and network events
simultaneously so this should not be that hard (and multiple threads
are probably not necessary). Of course, there are some pitfalls like
this (taken from Cygwin sources):

/* Some types of object (e.g., consoles) wake up on "inappropriate" events
like mouse movements. The verify function will detect these
situations.
If it returns false, then this wakeup was a false alarm and
we should go
back to waiting. */

But at least I'll try.

- Dmitry Bely

Kuba Ober

unread,
Feb 8, 2008, 8:27:35 AM2/8/08
to caml...@yquem.inria.fr

There's a windows API function for that. As long as the newtork access can be
wrapped in the usual aysnchronous I/O primitives, there's a wait function
that will wait on an async conditition *or* a message.

Cheers, Kuba

0 new messages