What is the difference between these two, and when would I use one over the other? SetPrivateState() doesn’t appear to modify the public state, and SetPublicState doesn’t appear to modify the private state, so it seems a little confusing that these can get out of sync with each other. What’s the use case here?
What is the difference between these two, and when would I use one over the other? SetPrivateState() doesn't appear to modify the public state, and SetPublicState doesn't appear to modify the private state, so it seems a little confusing that these can get out of sync with each other. What's the use case here?
When you detect the truth (when your process starts or stops), you set the private state. The public state could be set to running, but you are implementing a source line single step which may involve starting and stopping the process 100s of times before the step is actually done. So the thread plans use the private state and determine when the public state should be updated. Another example is running an expression. The public state may say "stopped", but privately the process can be resumed and stopped many times when evaluating the expression, but you wouldn't want the public (people listening to the process events) to know about such changes.
So the thread plans and process use the private state to make things happen and this tracks the "truth" of what the current process is doing. The public facing state is what causes the events to be broadcast to whomever is listening to the process events and should only notify the GUI or command line when it would like to update the views or display the stop reason, etc.
In the classes that are controlling your actual process, you should always be setting the private state. Never touch the public state yourself.
Thanks, makes sense.
A follow up question. Trying to make sure I get this right for the sequence of launching a process. You launch the process, wait for the initial stop, then lldb resumes your process, then it’s running. Conceptually it seems like the following state sequence makes the most sense
Upon returning from Process::DoLaunch() Public = Private = Launching
After the initial stop is received Public = launching, private = stopped
After LLDB calls DoResume() Public = private = running
On the other hand, you said I should never touch the public state myself. Did I understand this correctly, or is it ok to set the public state from within my process plugin?
Launching and attaching are funny in that we hijack the public events so they don't get delivered to the user. So in the launch and attach case you might need to set the public state directly. I would follow what the other plugins are doing. Once your process is launched and stopped, you won't ever play with the public state directly, but you might need to during launch and attach because the events are hijacked. When we hijack the public events, we can consume one or more events so they don't get delivered. For example, we have sync and async mode. In sync mode when you launch it expects you to wait until the process stops before returning from any commands that run the target. So your launch could actually consume all events and the process can exit. When you return from launch in sync mode, you can then just check the state of the process and see if you are stopped or exited. In async mode, we might get the first stop of the process (at the entry point with no code having been run), but continue your process for you if you didn't specify to stop at entry in your launch prefs. So we actually eat a public stop for the stop at the entry, and then resume the process but we don't consume that event...
Is there some documentation about async mode somewhere? I’ve looked at many of the relevant functions and can’t find a comment or anything describing it.
In async mode, is it ok to return from DoLaunch() before the initial stop is received? You mention that you get the first stop of the process at the entry point with no code having been run. I’m not sure if you meant this literally, but at least on Windows a very small amount of code actually will run before we get the initial stop. The initial stop is actually a breakpoint opcode embedded in the OS’s loader code, so execution has to to run to there before we get the stop. So is it ok if I create the process, return immediately with public = private = launching, then when we get the initial stop, check the whether the launch flag is set to stop at entry and update the private and public state accordingly?
Also, async / sync mode doesn’t seem to be in the ProcessLaunchInfo. Do I need to find a way to get at the top level Debugger object to find this out?