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

Fatal error: debugger does not support channel locks #10517

Closed
anentropic opened this issue Jul 15, 2021 · 14 comments
Closed

Fatal error: debugger does not support channel locks #10517

anentropic opened this issue Jul 15, 2021 · 14 comments

Comments

@anentropic
Copy link

I originally posted this on Stackoverflow, thinking it a problem with my code or some library incompatibility.
https://stackoverflow.com/questions/68394075/fatal-error-debugger-does-not-support-channel-locks

I had a reply there suggesting it was likely an issue with ocamldebug and macos and I should report it here, so I'll reproduce details below.

Firstly I am on macOS Catalina (10.15.7) on an Intel cpu.

I initially set up my project by:

brew install ocaml opam
opam switch create . ocaml-base-compiler.4.12.0
eval $(opam env)

I have added (modes byte exe) to my dune file.

When I run dune build I can see the bytecode file output, alongside the exe, as _build/default/bin/cli.bc

When I pass this to ocamldebug I get the following error:

ocamldebug _build/default/bin/cli.bc
	OCaml Debugger version 4.12.0

(ocd) r
Loading program... done.
Fatal error: debugger does not support channel locks
Lost connection with process 33035 (active process)
between time 170000 and time 180000
Restart from time 170000 and try to get closer of the problem ? (y or n)

If I choose y the console seems to hang indefinitely.

I found the source of the error here:

caml_fatal_error("debugger does not support channel locks");

  /* The code in this file does not bracket channel I/O operations with
     Lock and Unlock, so fail if those are not no-ops. */
  if (caml_channel_mutex_lock != NULL ||
      caml_channel_mutex_unlock != NULL ||
      caml_channel_mutex_unlock_exn != NULL)
    caml_fatal_error("debugger does not support channel locks");

...but I don't know what might be triggering it.

My project is using cmdliner and lwt ...I thought "channel I/O operations" might have something to do with either of those libraries.

But the replier on SO seemed to think it was more likely an OS-level issue with my install of ocamldebug itself.

@nojb
Copy link
Contributor

nojb commented Jul 15, 2021

I believe the message debugger does not support channel locks refers to the fact that the debugger does not support programs that enable multi threading via the threads library. Perhaps lwt does this indirectly?

@dra27
Copy link
Member

dra27 commented Jul 16, 2021

Does your project use lwt.unix?

@anentropic
Copy link
Author

anentropic commented Jul 16, 2021

@dra27 I think so, yes... indirectly via https://github.com/mirage/irmin/

@xavierleroy
Copy link
Contributor

We should have a better error message! But, yes, ocamldebug doesn't work with multithreaded programs.

@anentropic
Copy link
Author

ok thanks, good to know

looks like I need to temporarily vendor irmin into my project and put in some print debugging then

@dra27
Copy link
Member

dra27 commented Jul 19, 2021

If you are certain (and I mean really, really certain) that no threads are ever created, for debugging purposes only, you could recompile systhreads.cma with:

thread_initialize ();

commented out or, possibly less unsafely, these 3 lines commented out:

caml_channel_mutex_lock = caml_io_mutex_lock;
caml_channel_mutex_unlock = caml_io_mutex_unlock;
caml_channel_mutex_unlock_exn = caml_io_mutex_unlock_exn;

commented out. But you must be absolutely certain that no threads will be created.

@anentropic
Copy link
Author

seems pretty clear that lwt uses threads https://github.com/ocsigen/lwt/search?q=threads so I guess i'm out of luck

@xavierleroy
Copy link
Contributor

It would be nice if we could start ocamldebug on a program that was linked with the threads library and fail only when the first thread is actually created.

@anentropic
Copy link
Author

Out of curiosity, is this situation going to get better or worse with multi-core OCaml?

xavierleroy added a commit to xavierleroy/ocaml that referenced this issue Aug 31, 2021
…t threads

ocamldebug has never worked with multithreaded programs: multiple
threads mess up the communication protocol with the debugger, and the
fork()-based checkpointing mechanism breaks too.

Up to 4.11, the debugger would work fine until the first thread was
created.  Then, bizarre errors would be reported.

In 4.12 (commit e678885), a check was
added, causing any program linked with the threads library to report a
fatal error at start-up time when run under the debugger.

As reported in ocaml#10517, this check is too strong: some programs just
happen to be linked with the threads library, e.g. because they use
LWT, but may never start a thread.  There's no reason to refuse to
debug these programs.

This commit reverts the 4.12 change and adds a check in Thread.create
that aborts the program if it is run under the debugger.  This way,
programs linked with the threads library can still be debugged until
the point where they create new threads.
@xavierleroy
Copy link
Contributor

It would be nice if we could start ocamldebug on a program that was linked with the threads library and fail only when the first thread is actually created.

See #10594

@xavierleroy
Copy link
Contributor

Out of curiosity, is this situation going to get better or worse with multi-core OCaml?

As far as I know, no better and no worse, i.e. the debugger should remain compatible with single-domain, single-thread programs only.

xavierleroy added a commit that referenced this issue Aug 31, 2021
…t threads

ocamldebug has never worked with multithreaded programs: multiple
threads mess up the communication protocol with the debugger, and the
fork()-based checkpointing mechanism breaks too.

Up to 4.11, the debugger would work fine until the first thread was
created.  Then, bizarre errors would be reported.

In 4.12 (commit e678885), a check was
added, causing any program linked with the threads library to report a
fatal error at start-up time when run under the debugger.

As reported in #10517, this check is too strong: some programs just
happen to be linked with the threads library, e.g. because they use
LWT, but may never start a thread.  There's no reason to refuse to
debug these programs.

This commit reverts the 4.12 change and adds a check in Thread.create
that aborts the program if it is run under the debugger.  This way,
programs linked with the threads library can still be debugged until
the point where they create new threads.
xavierleroy added a commit that referenced this issue Sep 1, 2021
…10594)

ocamldebug has never worked with multithreaded programs: multiple
threads mess up the communication protocol with the debugger, and the
fork()-based checkpointing mechanism breaks too.

Up to 4.11, the debugger would work fine until the first thread was
created.  Then, bizarre errors would be reported.

In 4.12 (commit e678885), a check was
added, causing any program linked with the threads library to report a
fatal error at start-up time when run under the debugger.

As reported in #10517, this check is too strong: some programs just
happen to be linked with the threads library, e.g. because they use
LWT, but may never start a thread.  There's no reason to refuse to
debug these programs.

This commit reverts the 4.12 change and adds a check in Thread.create
that aborts the program if it is run under the debugger.  This way,
programs linked with the threads library can still be debugged until
the point where they create new threads.
@xavierleroy
Copy link
Contributor

#10594 is merged and adds a clearer error message + the ability to debug the program until it calls Thread.create. I think this is the best we can do without an extensive rewrite of ocamldebug. Hence I'll close this report.

@nikswamy
Copy link

nikswamy commented Mar 9, 2022

I'm using OCaml 4.12. My program does have some uses of Thread.create/join, and Mutex.lock/unlock.

When running my program using ocamldebug on Linux, it fails very quickly with Fatal error: debugger does not support channel locks.

However, running the same program on Windows/Cygwin does not exhibit this error and ocamldebug goes much further, until it eventually dies with Fatal error: exception Sys_error("An existing connection was forcibly closed by the remote host.\r\n")

Is there a reason for this difference in behavior? Thanks in advance!

@xavierleroy
Copy link
Contributor

The Windows/Cygwin behavior you describe is consistent with OCaml 4.11 or earlier. The "debugger does not support channel lock" error was introduced in 4.12 but should show up with Cygwin as well as with other systems.

The soon-to-be-released OCaml 4.14.0 should restore a 4.11-like behavior, namely: you can debug up to the point where the program creates its first thread.

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

No branches or pull requests

5 participants