Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Crash when debugging a program that calls Unix.fork() #4541

Closed
vicuna opened this issue Apr 24, 2008 · 4 comments
Closed

Crash when debugging a program that calls Unix.fork() #4541

vicuna opened this issue Apr 24, 2008 · 4 comments
Labels

Comments

@vicuna
Copy link

vicuna commented Apr 24, 2008

Original bug ID: 4541
Reporter: jsk
Status: closed (set by @damiendoligez on 2010-04-20T15:46:35Z)
Resolution: fixed
Priority: normal
Severity: crash
Platform: x86
OS: Ubuntu Linux
OS Version: 7.10
Version: 3.10.2
Fixed in version: 3.12.0+dev
Category: ~DO NOT USE (was: OCaml general)
Monitored by: bacam

Bug description

When debugging a bytecode program that calls Unix.fork(), ocamlrun
and ocamldebug usually crash immediately after the fork operation.

  1. Create a program called "test.ml", containing the following:

    let _ =
        Printf.printf "process %n starting\n" (Unix.getpid ());
        flush stdout;
        let _ = Unix.fork () in
        Printf.printf "process %n ending\n" (Unix.getpid ());
    
  2. Compile the program:

    "ocamlc -custom -g unix.cma test.ml -o test.exe".  
    
  3. Start the debugger, specifying the location of "unix.ml" and an
    explicit socket:

    "ocamldebug -I <path-to-unix> -s <socket-name> test.exe"
    
  4. Issue the following commands to ocamldebug:

    "set loadingmode manual"
    "goto 0"
    
  5. Manually load the program (possibly on another machine):

    "CAML_DEBUG_SOCKET=<socket-name> ./test.exe"
    
  6. Repeatedly issue the "step" command to ocamldebug.

At the point just after the call to Unix.fork(), ocamldebug usually
terminates with an error message of the form:

(ocd) Garbage data from process <n>
>> Fatal error: Debugcom.do_go
Uncaught exception: Misc.Fatal_error

Ocamlrun usually also terminates itself at this point.

This appears to be happening because ocamldebug is receiving unexpected
data from ocamlrun, presumably because the forked ocamlrun processes are
competing with one another to send data along the same connection to
ocamldebug.

Occasionally, though, ocamldebug doesn't crash, but continues to report
data from both parent and child ocamlrun processes. Issuing further step
commands to ocamldebug causes the forked processes to repond in a round-
robin style. Presumably this is because the forked ocamlrun processes
are still competing with one another to read data from the same shared
connection to ocamlbug, and are picking up commands alternately, one
after the other.

The current behaviour is making it difficult for us to debug programs
that launch other processes using the traditional "fork-exec" sequence,
since debugged programs have a very good chance of crashing immediately
after they call Unix.fork().

I'm wondering, is it possible to make ocamlrun aware of Unix.fork(),
so that a child ocamlrun process doesn't attempt to communicate with
ocamldebug through the same socket as its parent process?

Thanks for your help

Jonathan

Jonathan Knowles
Citrix Systems Research & Development

File attachments

@vicuna
Copy link
Author

vicuna commented Oct 20, 2009

Comment author: bacam

I've been playing around with ocamldebug support for fork a bit, and I'll attach a patch shortly. It works by closing the connection to one of the processes, and it includes a gdb-like option to pick whether to follow the parent or child process. One small wart is that I've added a stub implementation of the debugging functions to the native code runtime; another option would be to build two versions of the unix library.

The patch was made against 3.11.1, but applies to the trunk version too.

@vicuna
Copy link
Author

vicuna commented Apr 20, 2010

Comment author: @damiendoligez

I'm integrating the patch into the trunk. It will be in 3.12.0.

@vicuna vicuna closed this as completed Apr 20, 2010
@vicuna vicuna added the bug label Mar 19, 2019
@vthemelis
Copy link

vthemelis commented Aug 6, 2023

@damiendoligez, I think I'm having the same issue. I'm trying to debug a program that's using multi-processing and every so often the debugger just gives up. I'm using OCaml 4.14.1 so the patch above must be integrated. Do you know where I could find it?

I'm on M1 Mac if that makes a difference.

@xavierleroy
Copy link
Contributor

@vthemelis : as far as I can see, the patch in question is in 4.14 and 5.0:

if (caml_debugger_in_use)
if ((caml_debugger_fork_mode && ret == 0) ||
(!caml_debugger_fork_mode && ret != 0))
caml_debugger_cleanup_fork();

So, by default, ocamldebug will ignore the child process and remain attached to the parent process, unless you set the follow_fork_mode parameter (see https://v2.ocaml.org/releases/5.0/htmlman/debugger.html).

If it doesn't work for you, you could submit an issue, but please include a complete case to reproduce the issue.

If your program is using Unix.fork just to do Unix.exec in the child process, please consider using Unix.create_process instead: since OCaml 4.12, it is implemented in without calling Unix.fork, in a way that works better both with the debugger and with concurrency.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants