[m-rev.] for review: minimal support for ssdebug on multithreaded programs

Peter Wang novalazy at gmail.com
Thu Jun 24 15:26:39 AEST 2010


Branches: main, 10.04

Add an (undocumented) method for ssdebug, to allow debugging of only the
initial thread in a multi-threaded program.

ssdb/ssdb.m:
        Make the debugger_state mutable thread-local, so that all threads but
        the initial one can execute as if debugging is disabled.

        Add `pause_debugging' and `resume_debugging' predicates that the user
        must call around calls to `thread.spawn'.  Mercury only supports
        thread-local mutables which inherit their values from the parent
        thread, so when the thread is created the debugger_state mutable must
        be set to `off'.  The predicates may have other uses, too.

README.ssdebug:
        List debugging of multi-threaded programs as a limitation.

diff --git a/README.ssdebug b/README.ssdebug
index 658bf33..3522c61 100644
--- a/README.ssdebug
+++ b/README.ssdebug
@@ -90,4 +90,6 @@ LIMITATIONS
 
 - There is no I/O tabling.
 
+- Debugging of threaded programs is not supported.
+
 -----------------------------------------------------------------------------
diff --git a/ssdb/ssdb.m b/ssdb/ssdb.m
index 111cf61..3b8808d 100755
--- a/ssdb/ssdb.m
+++ b/ssdb/ssdb.m
@@ -20,8 +20,12 @@
 
 :- module ssdb.
 :- interface.
+
+:- import_module io.
 :- import_module list.
 
+%-----------------------------------------------------------------------------%
+
 :- type ssdb_proc_id
     --->    ssdb_proc_id(
                 module_name :: string,
@@ -103,6 +107,26 @@
 :- impure pred handle_event_redo_nondet(ssdb_proc_id::in,
     list_var_value::in) is det.
 
+%-----------------------------------------------------------------------------%
+
+:- type debugging_paused.
+
+    % These low-level predicates allow you to suspend the debugger temporarily.
+    %
+    % Debugging of multi-threaded programs is unsupported, but it is possible
+    % to debug the initial thread only, if you pause debugging while spawning
+    % a thread:
+    %
+    %   ssdb.pause_debugging(Paused, !IO),
+    %   thread.spawn(some_thread_proc, !IO),
+    %   ssdb.resume_debugging(Paused, !IO)
+    %
+    % The spawned thread will simply execute as if debugging was disabled.
+    % It will continue running in the background during debugger prompts.
+    %
+:- pred pause_debugging(debugging_paused::out, io::di, io::uo) is det.
+:- pred resume_debugging(debugging_paused::in, io::di, io::uo) is det.
+
 %----------------------------------------------------------------------------%
 %----------------------------------------------------------------------------%
 
@@ -113,7 +137,6 @@
 :- import_module bool.
 :- import_module char.
 :- import_module dir.
-:- import_module io.
 :- import_module int.
 :- import_module map.
 :- import_module maybe.
@@ -146,6 +169,8 @@
     --->    debugger_off
     ;       debugger_on.
 
+:- type debugging_paused == debugger_state.
+
 :- type stack_frame
     --->    stack_frame(
                 % Event Number
@@ -309,15 +334,19 @@ init_list_params = list_params(new_list_path, 2).
 :- mutable(saved_output_stream, io.output_stream, io.stdout_stream, ground,
     [untrailed, attach_to_io_state]).
 
-    % This must be after the tty streams.
-:- mutable(debugger_state, debugger_state, init_debugger_state, ground,
-    [untrailed, attach_to_io_state]).
+    % This is thread-local to allow debugging of the initial thread in
+    % multi-threaded programs.  As thread-local mutables inherit their values
+    % from the parent thread, the user must temporarily disable debugging while
+    % the child thread is created, using `pause_debugging'.
+    %
+:- mutable(debugger_state, debugger_state, debugger_off, ground,
+    [untrailed, thread_local, attach_to_io_state]).
 
-:- func init_debugger_state = debugger_state is det.
+:- initialise(init_debugger_state/2).
 
-init_debugger_state = DebuggerState :-
-    some [!IO] promise_pure (
-        impure invent_io(!:IO),
+:- pred init_debugger_state(io::di, io::uo) is det.
+
+init_debugger_state(!IO) :-
         io.get_environment_var("SSDB", MaybeEnv, !IO),
         io.get_environment_var("SSDB_TTY", MaybeTTY, !IO),
         (
@@ -351,8 +380,7 @@ init_debugger_state = DebuggerState :-
         ;
             DebuggerState = debugger_off
         ),
-        impure consume_io(!.IO)
-    ).
+    set_debugger_state(DebuggerState, !IO).
 
 :- pred add_source_commands(io::di, io::uo) is det.
 
@@ -436,6 +464,25 @@ step_next_stop(!IO) :-
 
 %-----------------------------------------------------------------------------%
 
+pause_debugging(Paused, !IO) :-
+    get_debugger_state(Paused, !IO),
+    (
+        Paused = debugger_off
+    ;
+        Paused = debugger_on,
+        set_debugger_state(debugger_off, !IO)
+    ).
+
+resume_debugging(Paused, !IO) :-
+    (
+        Paused = debugger_on,
+        set_debugger_state(debugger_on, !IO)
+    ;
+        Paused = debugger_off
+    ).
+
+%-----------------------------------------------------------------------------%
+
 set_context(FileName, Line) :-
     impure set_cur_filename(FileName),
     impure set_cur_line_number(Line).

--------------------------------------------------------------------------
mercury-reviews mailing list
Post messages to:       mercury-reviews at csse.unimelb.edu.au
Administrative Queries: owner-mercury-reviews at csse.unimelb.edu.au
Subscriptions:          mercury-reviews-request at csse.unimelb.edu.au
--------------------------------------------------------------------------



More information about the reviews mailing list