And one more reply that didn't go to the list. Really sorry :/. Original message, plus an edit:
The piggy backing of events is fine from my point of view as long as i can check the interrupted flag (for which i'll try to compose a patch). My issues stem more from the fact that i have to concurrently operate on the process (event loop thread, JDWP thread). The "hook" breakpoints are actually handled on the event loop thread, including the auto-resume, which is a requirement for our JDWP implementation to work correctly. The JDWP client shouldn't know that the process hit a "hook" breakpoint. My problem is really this: the JDWP thread stops the event loop thread. Next it stops the process via SBProcess::Stop (which calls Process::Halt). Sadly, Process::Halt doesn't set the state on the process. I have to poll events on the JDWP thread for that to happen, on the JDWP thread, until i get a stopped (or exited/crashed/...) event. I then have to re-broadcast those events so the event loop thread can later process them once i resume it. I'm very worried about re-broadcasting events as i don't know what havoc that will wreck in the LLDB internal state. Ideally, Process::Halt (and hence SBProcess::Stop()) would set things up in a way where i don't have to poll events on the JDWP thread. It should also set the process state accordingly. I also noticed strange timing bugs when calling SBProcess::Stop() while a previous SBProcess::Continue() is still being propagated to the inferior. That's actually what causes the eStopReasonInvalid events i talked about in another thread. I just played around with the Python API. Turns out i've been using SBListener::WaitForEvent incorrectly. I supplied 0 for timeout, assuming it would return immediately. This actually throws an assertion when called via the Python API. Our JNI wrapper of LLDB doesn't throw an assert. I guess SBListener::PeekAtNextEvent is what i should use instead for non-blocking event processing? As always, really appreciate that you take the time to read and answer my walls of text. On Mon, Oct 27, 2014 at 7:02 PM, Greg Clayton <gclay...@apple.com> wrote: > > > On Oct 26, 2014, at 5:23 AM, Mario Zechner <badlogicga...@gmail.com> > wrote: > > > > Sorry for the mail bomb. After some more investigation, it's the > inferior's responsibility to deal with SIGSTOP itself, e.g. interpret and > act upon errno == EINTR. Lucky, our runtime library already seems to take > care of EINTR properly and supports "restartable" I/O. So i guess i > answered question 2 myself. Progress :) > > > Glad you figured this out, I was about to mention EINTR and handling those > correctly. > > > For question 1, i'd like to elaborate on the scenario: > > > > - We have one event loop thread constantly polling events from the > process via SBListener::WaitForEvent > > - We setup a few breakpoints in our runtime to get to know about things > like thread creation/death and so on. When such a "hook" breakpoint is hit, > we read whatever information we need from the inferior and then > automatically resume the process via SBProcess:Continue. All this happens > on the event loop thread, in response to breakpoint stop events with the > appropriate location. > > - We have a second thread, let's call it JDWP thread, that listens for > JDWP commands. When a command arrives, we need to stop the inferior, > perform the command, and resume the inferior. For this we temporarily > disable the event loop thread (no more calls to WaitForEvent, hence no > "Hook" breakpoint processing, hence no calls to SBProcess::Continue on the > event loop thread), call SBProcess::Stop(), perform our command, call > SBProcess::Continue and then reenable the event loop thread. > > > > This setup has one issue, which relates to my first question > (stop/breakpoint event taken over by SBProcess::Halt and marked as > interrupted). When we stop the event loop thread and then call > SBProcess::Stop(), one of three things can happen: > > > > 1) the process was already stopped -> Process::Halt returns immediately, > no additional events are generated > > 2) the process wasn't stopped yet, so Process::Halt sends SIGSTOP and an > event with stop reason eStopReasonSignal will eventually be generated and > broadcast to the SBListener in the event loop thread > > 3) the process wasn't stopped yet, while Process::Halt does its thing a > stop event arrives (e.g. breakpoint) and is consumed by Process::Halt. > Process::Halt takes over that event, marks it as interrupted then > rebroadcasts it. > > > > In case 3 (breakpoint event is taken over and marked) we don't want to > automatically resume the process. That's why we need to be able to decipher > if the event was marked as interrupted, so we can decide whether the JDWP > thread should actually resume the process once its done responding to the > JDWP request. > > An easy way to deal with this is to take the race out by having your event > thread do the resume and don't have your breakpoint do the auto resume. > More generically, we do need LLDB to be able stop the auto-resume stuff > from happening. To clarify your case #3 above: you are still getting a stop > event, just not a eStopReasonSignal? No stop reason? > > If a plug-in sends a "SIGSTOP" in order to stop a process, we really > should be not showing that to the user as the reason for the stop like we > are now, we should be covering it up and giving a new > eStopReasonInterrupted for a thread instead IMHO. If we did this, would > this clear up your issues? > > > > Sorry for the wall of text. I feel my adventure notes here may serve > others to navigate LLDB for similar use cases :) > > > > Thanks, > > Mario > > > > On Sun, Oct 26, 2014 at 11:59 AM, Mario Zechner <badlogicga...@gmail.com> > wrote: > > Just to clarify my use of "interrupted". Of course all threads should be > stopped upon SBProcess::Stop(). However, upon SBProcess:Resume() I/O > operations shouldn't just return due to the SIGSTOP but continue doing what > they did before receiving the signal. > > > > Thanks, > > Mario > > > > On Sun, Oct 26, 2014 at 11:56 AM, Mario Zechner <badlogicga...@gmail.com> > wrote: > > Hi, > > > > i'm currently trying to understand how LLDB interrupts/resumes > processes. To my understanding, the Process implementation sends a SIGSTOP > to the inferior, which will stop the process. Alternatively, the process > may be stopped (e.g. breakpoint) while Process::DoHalt is executing, in > which case the event is marked as interrupted. I have a few questions > regarding this: > > > > 1) How can i check wether an event was marked as interrupted via the > API? SBProcess has a couple of static methods like GetStateFromEvent, but > none of these allow me to check if the event was marked as interrupted > > 2) SIGSTOP seems to interrupt any I/O call, e.g. getchar, listen, and so > on. Upon a resume, these functions will simply return (e.g. returning EOF) > instead of continuing waiting for input. Is there any way to have this not > happen? > > > > Our problem is, that we need to stop/resume the process to implement > parts of JDWP (Java debugging wire protocol). Some JDWP commands require us > to stop the process, read some memory regions and resume the process again, > letting the inferior think that nothing has happened. All of this should > not interfere with normal program execution, e.g. a file read shouldn't be > interrupted because we stopped the inferior via SBProcess:Stop(). > > > > As always, thanks for all your help! > > > > ciao, > > Mario > > > > > > _______________________________________________ > > lldb-dev mailing list > > lldb-dev@cs.uiuc.edu > > http://lists.cs.uiuc.edu/mailman/listinfo/lldb-dev > >
_______________________________________________ lldb-dev mailing list lldb-dev@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/lldb-dev