Thank you for your help.
What is the reason for using SBLaunchInfo over calling tgt.Launch with the launch configuration as a set of parameters?
The code is much clearer on what arguments mean what. In your current launch call, it is hard to know what all arguments mean and would be easy to put
SBProcess proc = tgt.Launch(
listen,
nullptr,
nullptr,
nullptr,
“targetout.txt”,
nullptr,
“./”,
eLaunchFlagExec | eLaunchFlagDebug,
false,
error
);
New code:
SBError error;
SBListener listen;
const char argv[] = { “arg1”, “arg2” };
SBLaunchInfo launch_info(argv);
launch_info.SetListener(listen);
launch_info.SetWorkingDirectory(getcwd());
launch_info.AddOpenFileAction(STDOUT_FILENO,“**targetout.txt”, false, true);
launch_info.SetLaunchFlags(eLaunchFlagExec | eLaunchFlagDebug);
SBProcess proc = tgt.Launch(info, error);
You can see what each argument means above a bit more clearly. This also means you can create a SBLaunchInfo object before parsing the options, and using the options you could lazily populate the launch info object, then use it to launch.
Furthermore I do not see a way to set stdout, stdin, and stderr for the launched process by using SBLaunchInfo.
bool SBLaunchInfo::AddOpenFileAction(int fd, const char *path, bool read, bool write);
I have a question regarding the event loop.
Is lldb thread-safe enough such that I can run that loop in another std::thread while simultaneously using other debugger functions?
Yes you can. I would suggest being careful though as you wouldn’t want to try and display variables from a current frame while another thread is resuming the process. The code will work, but some calls might fail when the process does resume. We usually run a thread that listens for events, and when handling these events, it might do things like display all local variables in the IDE when a eStateStopped event is detected.
Some IDEs maintain a stack of work items to do. Say the user hits step 5 times really quickly by pressing F11 5 times, it is a good idea to make a queue of things to do for the debugger, and the stack now contains 5 “step over” commands. The IDE in the event loop will wait for the process to stop, check the command queue, and if there is another command in there, it could skip displaying the variables and updating all of the views and instead just pop one of the “step over” commands from the queue and do that. Once you stop and the queue is empty, you can show variables and stack traces, etc. Also, you might implement a timeout of .5 seconds after a stop before you show the variables in case the user continues or steps again really quickly. The user might also hit step a bunch of times and then click stop. Some IDEs flush the command queue to ensure we stop when the user hits the stop button to ensure we don’t keep stepping too long.
So just be careful to think about the logic you want. If you stop your process, it is a good idea to grab the variables and get their values on the same thread that is controlling the process so you don’t end up with your variable view trying to display variables as the process resumes. It is also a good idea to take the user input (step, continue, kill) and queue them up and consume those events in your event loop.
Let me know if that makes sense,
Greg Clayton