RE: MI threads behaviour

Marc Khouzam
2008-07-10T13:14:45Z

Hi,

> Threads management in GDB
> =========================
>
> CLI interface
> =============
>
> In CLI mode, GDB maintains the current thread and current frame -- which
> are specified by the user, with commands like 'thread', 'frame' and 'up/down'.
> Most of the operation, such as printing variable values, work in context of
> the current thread/frame. In all-stop mode, GDB will also implicitly switch
> current thread/frame to the thread that has stopped. In non-stop mode, GDB
> never automatically switches the thread.
>
> It is possible that the current thread exits. In non-stop mode, GDB will
> automatically reset the 'current thread' to an invalid value. Essentially
> no commands are allowed after that, and user must switch to some still-alive
> thread. In all-stop mode, GDB does not allow commands until it stops, and it
> does not stop on thread exit. So, if a thread exits, GDB continues to execute
> the program until an event in some other thread happens -- in which case it
> switches to that other thread automatically. In
> all-stop/sync/scheduler-locking-on mode the user will have to use Ctrl-C after
> the current thread exits to stop some other thread.

I'm not familiar with scheduler-locking-on, so I'm not sure if it is relevant
to my question, but I believe that in all-stop, one can use Ctrl-C to force
GDB to stop; if the thread that was executing has exited, and the user then
uses Ctrl-C, what thread will GDB point to when it stops?

> MI interface
> ============
>
> In MI mode, there are two current threads -- the current thread as shown in
> UI, and the current thread from GDB point of view. The frontend should either
> avoid relying on GDB current thread, or make sure to switch GDB current
> thread as necessary. Also, we expect the frontend to notice when user requests
> a change in current thread via a CLI command such as 'thread', or a
> user-defined command, and update the UI current thread. There are two
> possible approaches:
>
> 1. The recommended way is to use the --thread option for all MI
> commands, and this makes the GDB current thread almost irrelevant.
>
> GDB will have a new notification, =thread-selected, which is used to
> report to the frontend that during processing of the last MI command,
> GDB discovered user's request to change current thread to something.
> Internally, this will be implemented by checking of the GDB current
> thread has changed when we're done with processing MI command.
> In all-stop mode, the notification will be emitted when any thread stops.
>
> The CLI behaviour of setting GDB current thread to invalid value if the
> current thread exits will be preserved, but is of limited value, since
> the frontend does not depend on current thread directly, and will be notified
> about thread exit anyway. Therefore, no notification will be emitted in
> this case.
>
> The notification will be emitted even if the thread user requested to be
> selected is the same as currently selected thread. Imagine the frontend
> has two windows open -- in one, UI has thread 1 selected, and in another,
> UI has thread 2 selected. If user types "thread 2" in GDB console in the
> first window, would expect the first window UI to switch to thread 2. So,
> the notification should be emitted even if GDB current thread is 2,
> already.
>
> To summarize:
> - With --thread option, frontend should not care at all about GDB's
> current thread. There's no need to ever send -thread-select
> - GDB will emit =thread-changed, and =frame-changes notification, which
> should be interpred as saying "I think that user wants, via CLI,
> to switch to this thread/frame"

=thread-changed or =thread-selected? Not a big deal, but I think
=thread-selected is better since:
"The notification will be emitted even if the thread user requested to be
selected is the same as currently selected thread"

> 2. The frontends not willing to upgrade to use the --thread option may use
> -thread-select prior the sending the actual MI command, and optionally
> -thread-select after the command.
>
> In this case, the frontend should, in addition to maintaining current thread
> as in UI, also remember which thread is current in GDB, and whenever sending
> a command that should be executed in a thread different from the current GDB
> thread, switch GDB to the desired thread. In particular, if sending several
> commands at once, one of which can be CLI command, the frontend should be
> prepared for the CLI command to change current thread. Frontend should never
> ever send a command to GDB's pipe if it previously sent a CLI command and
> haven't yet got its output back.

Is it the output of the CLI command that should be used to know the current
thread has changed? Or is it the =thread-selected notification of (2) below?

> The =thread-selected notification, in this case, should be interpreted to
> mean:
> (1) User's request that the selected thread be changed, and
> (2) Notification that GDB current thread has changed
> The (2) trait does not matter if --thread is used, but in this case the
> frontend need to use this information to figure if -thread-select should be
> sent.

Here, I believe there is a race condition. In the example you give above with
two windows, one window could send a CLI command changing the thread, but
the second window may send an MI command, before receiving the
=thread-selected notification and will act on the wrong thread.
I don't see how we could fix this.
Or maybe I misunderstood your explanation?

> Note that conceptually, the --thread option is equivalent to -thread-select,
> followed by the command, followed by -thread-select back to the original
> thread (unless the command been executed changes thread itself), followed by
> -stack-select-frame for old fram. The --thread option is allowed whenever
> the -thread-select command is.
>
> Threads and non-stop
> ====================
>
> To simplify initial implementation, we allow *all* MI commands even if
> inferiour is running. Furthermore, we don't care if the command tries to
> work on a running thread. If the command requires that the thread be stopped,
> it will error out, eventually. We don't try to pick a stopped thread and
> execute the command there. For now, let's decide it's frontend problem.

Looks good overall.

thanks

marc