Restore basic functionality to the bytecode debugger#11065
Restore basic functionality to the bytecode debugger#11065xavierleroy merged 17 commits intoocaml:trunkfrom
Conversation
|
I was also looking at this, but you are more advanced. If I can help with reviews or testing, let me know. |
43a3913 to
ebd3403
Compare
|
This looks rather good to me. Why don't you remove the Draft status so that it can get reviewed properly? |
|
Ping. Why don't you remove the Draft status so that it can get reviewed properly? |
d9f30d9 to
3a4746d
Compare
|
Stack backtrace is now working. The |
xavierleroy
left a comment
There was a problem hiding this comment.
Looks good to me. Thanks a lot for this work.
I was able to run the demo program for effects from the OCaml 5 manual. It's fun to step through all these continuations...
I added a commit that stops the debuggee cleanly if it spawns a domain. This way we can still debug up to the point where a domain is created. This is like #10594.
|
A bit of code may have been lost during the PR and this should probably be added because the trap barrier doesn't seem to work anymore: diff --git a/runtime/debugger.c b/runtime/debugger.c
index 187f681135..a220915784 100644
--- a/runtime/debugger.c
+++ b/runtime/debugger.c
@@ -560,6 +560,8 @@ void caml_debugger(enum event_kind event, value param)
caml_flush(dbg_out);
break;
case REQ_SET_TRAP_BARRIER:
+ i = caml_getword(dbg_in);
+ CAMLassert(i == frame_block_number(frame_block));
i = caml_getword(dbg_in);
Caml_state->trap_barrier_off = -i;
break;I noticed the problem, thanks to @OlivierNicole, while trying to review this PR (I'm very new to bytecode and ocamldebug). However, I don't think it's enough and |
|
@fabbing Thanks for finding this problem. This breaks the |
0a3e028 to
dd23dd0
Compare
|
This is better than the "depth" in terms of number of fibers but will run into troubles if the fiber is reallocated since the |
dc48cac to
f2913a2
Compare
|
Adapted to use fiber IDs instead of addresses. |
|
I've resumed reviewing the PR and it looked good to me. It's not straightforward to debug such test as many fork are involved in the process. |
|
With the OCaml 5 runtime you cannot safely call |
| i = fork(); | ||
| Lock (dbg_in); | ||
| Lock (dbg_out); | ||
| caml_acquire_domain_lock (); |
There was a problem hiding this comment.
Comparing this code with caml_atfork_default in domain.c, maybe you need to call caml_reset_domain_lock before re-acquiring the lock?
|
Thanks a lot for the hint @gasche. I had a look in that direction but it turns out to be something different: This test raises an exception ( A not very graceful solution is to set --- a/runtime/caml/io.h
+++ b/runtime/caml/io.h
@@ -115,6 +115,8 @@ CAMLextern struct channel * caml_all_opened_channels;
#define Flush_if_unbuffered(channel) \
if (channel->flags & CHANNEL_FLAG_UNBUFFERED) caml_flush(channel)
+CAMLextern void caml_channel_forget_last(void);
+
/* Conversion between file_offset and int64_t */
#define Val_file_offset(fofs) caml_copy_int64(fofs)
diff --git a/runtime/debugger.c b/runtime/debugger.c
index 861c37e3bb..448098e2fb 100644
--- a/runtime/debugger.c
+++ b/runtime/debugger.c
@@ -143,6 +143,7 @@ static void open_connection(void)
private to this code and never used concurrently. */
Lock (dbg_in);
Lock (dbg_out);
+ caml_channel_forget_last();
if (!caml_debugger_in_use) caml_putword(dbg_out, -1); /* first connection */
#ifdef _WIN32
@@ -479,6 +480,7 @@ void caml_debugger(enum event_kind event, value param)
i = fork();
Lock (dbg_in);
Lock (dbg_out);
+ caml_channel_forget_last();
caml_acquire_domain_lock ();
if (i == 0) {
close_connection(); /* Close parent connection. */
diff --git a/runtime/io.c b/runtime/io.c
index 78bfea6d8a..fae4d6239e 100644
--- a/runtime/io.c
+++ b/runtime/io.c
@@ -106,6 +106,11 @@ CAMLexport void (*caml_channel_mutex_unlock_exn) (void)
/* List of opened channels */
CAMLexport struct channel * caml_all_opened_channels = NULL;
+CAMLexport void caml_channel_forget_last(void)
+{
+ last_channel_locked = NULL;
+}
+
/* Basic functions over type struct channel *.
These functions can be called directly from C.
No locking is performed. */Thanks again to @OlivierNicole for his help in understanding channel behaviour. Unfortunately, this Investigation continues! |
Significant changes were added since this review, and the PR is not ready yet.
2eba56d to
8bb3526
Compare
Fixed by 3b34535, let's see if the testsuite passes now. |
|
Do we also want a "symmetrical" behavior with --- a/runtime/interp.c
+++ b/runtime/interp.c
@@ -1284,6 +1284,7 @@ value caml_interprete(code_t prog, asize_t prog_size)
goto do_resume;
do_resume: {
+ check_trap_barrier_for_effect(domain_state);
struct stack_info* stk = Ptr_val(accu);
if (stk == NULL) {
accu = Field(caml_global_data, CONTINUATION_ALREADY_TAKEN_EXN);Either way it looks good to me! |
Yes, but please leave me 1-2 weeks to work on it. I'm thinking about a radical solution to the locking problems that have plagued this PR. Stay tuned. |
|
Here is a preview of the "radical solution" I propose: damiendoligez#7 Ideally, I should make a separate PR with the basic changes, have it merged, and then you would rebase this PR on top of this work. But first I'd like you (@damiendoligez , @fabbing , ...) to have a quick look at the approach and comment. |
…have the CHANNEL_FLAG_MANAGED_BY_GC flag.
messages right and install it so the debugger can step through it.
Otherwise the debugger gets all confused. It is still possible to debug the program up to the point it spawns a new domain. This is the same solution we used in ocaml#10594 for programs that create threads.
Patch written by @fabbing, slightly adapted by Damien Doligez.
They are used in a single-threaded manner. Locking is no longer necessary since ocaml#11356. Also remove the recently-added caml_channel_reset_last_locked() function which is no longer needed.
3b34535 to
10dcb5f
Compare
|
I took the liberty to rebase on trunk and hand-merge damiendoligez#7. I'm running a CI precheck test. |
|
precheck is at https://ci.inria.fr/ocaml/job/precheck/726/ |
xavierleroy
left a comment
There was a problem hiding this comment.
Test results are as positive as they can be, and the whole PR is in good shape as far as I can see, so let's merge! Thanks @damiendoligez for all the work.
* debugger: the main program is now code fragment number 3 instead of 0 * debugger: update to handle stack backtrace in the presence of fibers * Fix embedded file name (and line number) for stdlib.ml.in to get error messages right and install it so the debugger can step through it. * Stop cleanly if a program being debugged spawns a domain. It is still possible to debug the program up to the point it spawns a new domain. This is the same solution we used in #10594 for programs that create threads. * fix the trap barrier and make it work with algebraic effects (aka fibers) * use Caml_inline instead of inline * debugger: use fiber id instead of address * re-enable debugger tests * re-enable dynlink debugging (cherry picked from commit 4e8f384)
|
Cherry-picked in 5.0: b4a61f5 |
This is work in progress.I still need to figure out what must be done to handle backtraces in the presence of fibers.[edit: now it's ready]