I dug into this some more. Windows is not using editline, so it's using the 
LLDB_DISABLE_LIBEDIT code path.

IOHandlerEditline::GetLine() will print the prompt, then get the next line. 
Type in a command, and it will continue doing this. The prompt comes out before 
the command finishes (in this case, anyway), so we get the prompt, then the 
output from the command, then nothing.

I've got a simple solution that works for hitting breakpoints and stepping, at 
least. In IOHandlerEditline::PrintAsync(), in the LLDB_DISABLE_LIBEDIT code 
path, print the prompt after calling IOHandler::PrintAsync().

I'll put up a patch to phabricator.

--
Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux 
Foundation Collaborative Project


-----Original Message-----
From: Greg Clayton [mailto:gclay...@apple.com] 
Sent: Monday, March 21, 2016 1:01 PM
To: Ted Woodward <ted.woodw...@codeaurora.org>
Cc: LLDB <lldb-dev@lists.llvm.org>
Subject: Re: [lldb-dev] Windows lldb prompt issue

All input and output are handled by IOHandler subclasses. There is a stack of 
them. When you start LLDB you get one thing on the IOHandler stack: the LLDB 
command interpreter:

IOHandlers:
[0] IOHandlerEditline for command interpreter

If you type "script" at the LLDB command prompt, the command interpreter pushes 
a IOHandlerPythonInterpreter onto the stack and all STDIN/OUT/ERR. Now your 
stack looks like:

[0] IOHandlerEditline for command interpreter [1] IOHandlerPythonInterpreter

When you type "quit()" in the IOHandlerPythonInterpreter, it will exit and pop 
off and return to:

[0] IOHandlerEditline for command interpreter

Note that these transitions happen on the same thread, so it is very easy to 
coordinate the output since it all happens in one thread of execution. 

When your process runs, by typing "run" on the command interpreter, the Process 
might push an IOHandler onto the stack so that when the process resumes you can 
do STDIN and receive any STDOUT/STDERR when your program runs, but it does so 
from _another_ thread. This is the only IOHandler that does things this way. So 
as soon as your resume a process that you have launched (if you attach, you 
don't get STDIN/OUT/ERR) we push the IOHandlerProcessSTDIO. When you stop, we 
must pop the IOHandlerProcessSTDIO. Again, this popping of the 
IOHandlerProcessSTDIO happens on another thread, not from the thread that is 
running the command interpreter. So this is why we have trouble coordinating 
the output. The threads the LLDB driver has are as follows:

1 - thread that runs the command interpreter
2 - thread that listens for debugger events (this includes process events for 
stops and runs)
3 - private process state thread that tracks any starts and stops and figure 
out when the send a public state change event

Thread 3 might start and stop a process 10 times for one source level single 
step, but it will only send out one public eStateRunning event and one 
eStateStopped event. So when a public eStateStopped event get delivered from 
thread 3 to thread 2, we set off a chain of events where we must pop the 

So when a stopped event comes in, thread 2 receives the eStateStopped event and 
will handle flushing any pending STDOUT and STDERR and then pop the 
IOHandlerProcessSTDIO. When anyone wants to display text on the top IOHandler's 
output file, the must coordinate with the IOhandler stack. This is done by 
calling:

void
Debugger::PrintAsync (const char *s, size_t len, bool is_stdout);

This coordinates with the top IOHandler by calling:

void
IOHandler::PrintAsync (Stream *stream, const char *s, size_t len);

Now the command interpreter, when active will print its prompt of "(lldb) ". 
When async output comes in, it will eventually end up calling:

void
Editline::PrintAsync (Stream *stream, const char *s, size_t len) {
    Mutex::Locker locker(m_output_mutex);
    if (m_editor_status == EditorStatus::Editing)
    {
        MoveCursor(CursorLocation::EditingCursor, CursorLocation::BlockStart);
        fprintf(m_output_file, ANSI_CLEAR_BELOW);
    }
    stream->Write (s, len);
    stream->Flush();
    if (m_editor_status == EditorStatus::Editing)
    {
        DisplayInput();
        MoveCursor(CursorLocation::BlockEnd, CursorLocation::EditingCursor);
    }
}

This clears the current line, so it erases the "(lldb) ", prints the output in 
"stream", the it must refresh the current IOHandler, which for out command 
interpreter will restore the "(lldb) " prompt.

So the question is: does the erase/print/restore feature in 
Editline::PrintAsync() even work on windows? I know that there is an Editline 
implementation on windows, but I am not sure it will do the right thing in this 
case as we are printing control characters to the screen in order to clear the 
"(lldb) " prompt with:

    if (m_editor_status == EditorStatus::Editing)
    {
        MoveCursor(CursorLocation::EditingCursor, CursorLocation::BlockStart);
        fprintf(m_output_file, ANSI_CLEAR_BELOW);
    }

Then we write the "Stream" content. So after a very long story, you might 
better understand what is happening. It would be worth testing something on 
windows where you just call Debugger::PrintAsync() while the "(lldb) " prompt 
is up and on the screen and see what happens. If this isn't working, then we 
know why the issue is happening. So if you have the following displayed in the 
LLDB driver:

"(lldb) "

And you call "Debugger::PrintAsync("hello world\n", 12, true)" on a thread that 
is not thread 1 from the initial thread list shown at the beginning, you should 
see your screen be:

"hello world
(lldb) "

If you see:

"(lldb)
hello world
(lldb) "

Then you know that the erasing feature isn't working in Editline::PrintAsync() 
and it will explain why you see this issue.

Greg Clayton

> On Mar 21, 2016, at 10:10 AM, Ted Woodward via lldb-dev 
> <lldb-dev@lists.llvm.org> wrote:
> 
> I run lldb on Windows and Linux, launching my gdb-server based Hexagon 
> simulator automatically on a process launch. On Windows I’m seeing the (lldb) 
> prompt before the stop message, and no prompt after. On Linux I see the 
> prompt after.
>  
> Windows:
> Current executable set to 'u:\lldb_test\factwin' (hexagon).
> (lldb) b main
> Breakpoint 1: where = factwin`main + 28 at factorial.c:32, address = 
> 0x00005130
> (lldb) r
> Process 1 launched: 'u:\lldb_test\factwin' (hexagon)
> (lldb) Process 1 stopped
> * thread #1: tid = 0x0001, 0x00005130 factwin`main(argc=1, argv=0x0000e110) + 
> 28 at factorial.c:32, stop reason = breakpoint 1.1
>     frame #0: 0x00005130 factwin`main(argc=1, argv=0x0000e110) + 28 at 
> factorial.c:32
>    29     }
>    30   */
>    31
> -> 32     base = 10;
>    33
>    34     printf("Factorial of %d is %d\n", base, factorial(base));
>    35     return 0;
>  
>  
> Linux:
> Current executable set to '/usr2/tedwood/lldb_test/factorial' (hexagon).
> (lldb) b main
> Breakpoint 1: where = factorial`main + 28 at factorial.c:32, address = 
> 0x00004130
> (lldb) r
> Process 1 launched: '/usr2/tedwood/lldb_test/factorial' (hexagon) 
> Process 1 stopped
> * thread #1: tid = 0x0001, 0x00004130 factorial`main(argc=1, argv=0x0000b100) 
> + 28 at factorial.c:32, stop reason = breakpoint 1.1
>     frame #0: 0x00004130 factorial`main(argc=1, argv=0x0000b100) + 28 at 
> factorial.c:32
>    29     }
>    30   */
>    31
> -> 32     base = 10;
>    33  
>    34     printf("Factorial of %d is %d\n", base, factorial(base));
>    35     return 0;
> (lldb)
>  
>  
>  
> Any idea why the prompt is coming out before the stop message?
>  
>  
> --
> Qualcomm Innovation Center, Inc.
> The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, 
> a Linux Foundation Collaborative Project
>  
> _______________________________________________
> lldb-dev mailing list
> lldb-dev@lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev


_______________________________________________
lldb-dev mailing list
lldb-dev@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev

Reply via email to