If you have redirections for stdin/out/err, don't use PseudoTerminal. The whole reason the PseudoTerminal utility class is there is to provide something that "does the right thing" when using ptys. If we aren't using master/slave you should just manually fork.
On Mar 29, 2014, at 9:24 AM, Eran Ifrah <[email protected]> wrote: > Hi, > > Testing further seems like that it does fixes the redirection thing when > using lldb as a library. > However, the more common case of using lldb from the command line fails > miserably :( > > There are 2 options here that I have looked into: > - Use the above hack with some more conditions that will ensure that the hack > will only kicks when redirection is actually requested (e.g. the terminal is > different from the current process terminal) > - Try and fix PseudoTerminal::Fork() to accept the requested terminal (so it > will not _always_ call to 'OpenFirstAvailableMaster') > > What do you think? > Eran > > > > > > On Fri, Mar 28, 2014 at 8:16 PM, Eran Ifrah <[email protected]> wrote: > Hi all, > > I finally had some time to build lldb in debug mode and debug through the > problem. > It seems that the problem is caused in this function: > > ProcessPOSIX::GetFilePath(...) > > This check: > > // By default the stdio paths passed in will be pseudo-terminal > // (/dev/pts). If so, convert to using a different default path > // instead to redirect I/O to the debugger console. This should > // also handle user overrides to /dev/null or a different file. > if (!path || ::strncmp(path, pts_name, ::strlen(pts_name)) == 0) > path = default_path; > > Note that when redirecting to a terminal, "path" will most likely be in the > form of "/dev/pts/XX" > and since "pts_name" is set to "/dev/pts/" (its hardcoded at the top of this > function) the above condition is always true > > So "path = default_path" will return a NULL pointer instead of the desired pts > > commenting this part of the "if" statement fixes the problem: > ::strncmp(path, pts_name, ::strlen(pts_name)) == 0 > > Can anyone explain what was the rational behind this check? > > Thanks, > Eran > > > On Wed, Mar 26, 2014 at 11:09 PM, Piotr Rak <[email protected]> wrote: > Sorry, we do have O_CREAT and even when open failed we'd exit with different > exit code earlier. > I'll rather go sleep - enough for today. :) > > > 2014-03-26 22:01 GMT+01:00 Piotr Rak <[email protected]>: > > Also other option is that we don't have O_CREAT in flags and we get ENOENT > from open().... but again can not check that today. > > > 2014-03-26 21:52 GMT+01:00 Piotr Rak <[email protected]>: > > No, closing before dup2 is not required, it should close fd and it should be > also atomic. I am wondering now if LLDB sets FileActions like it was > expecting that we use posix_spawn. > > I can not check it today... but will look at it tomorrow or during weekend. > > > 2014-03-26 21:33 GMT+01:00 Greg Clayton <[email protected]>: > > Looks like you might need to look at: > > ProcessMonitor::Launch(LaunchArgs *args) > > It is what does the fork + exec. > > It also looks like no matter what is sent to > ProcessMonitor::Launch(LaunchArgs *args) for stdin, stdout, stderr, Linux > _always_ launches using a pseudo terminal by doing: > > lldb_utility::PseudoTerminal terminal; > if ((pid = terminal.Fork(err_str, err_len)) == -1) > > > If you look at the "terminal.Fork()" code you will see that it actually sets > stdin/out/err to the slave slide of the pseudo terminal, so there is no > telling if the code in ProcessMonitor::Launch(): > > if (stdin_path != NULL && stdin_path[0]) > if (!DupDescriptor(stdin_path, STDIN_FILENO, O_RDONLY)) > exit(eDupStdinFailed); > > if (stdout_path != NULL && stdout_path[0]) > if (!DupDescriptor(stdout_path, STDOUT_FILENO, O_WRONLY | > O_CREAT)) > exit(eDupStdoutFailed); > > if (stderr_path != NULL && stderr_path[0]) > if (!DupDescriptor(stderr_path, STDERR_FILENO, O_WRONLY | > O_CREAT)) > exit(eDupStderrFailed); > > > Will work? ProcessMonitor::DupDescriptor() does: > > > bool > ProcessMonitor::DupDescriptor(const char *path, int fd, int flags) > { > int target_fd = open(path, flags, 0666); > > if (target_fd == -1) > return false; > > return (dup2(target_fd, fd) == -1) ? false : true; > } > > I would assume you would need to call close() on stdin/out/err first? Again > the PseudoTerminal::Fork() has always already setup stdin/out/err to the > slave side and the DupDescriptor calls are probably failing. > > Greg > > > On Mar 26, 2014, at 12:26 PM, Piotr Rak <[email protected]> wrote: > > > Hi, > > > > That got me curious and now I am bit confused how it works, and it should > > be really simple. > > > > I've checked Greg's example, it will just exit before main doing nothing. > > I've no idea why yet, however I attached my perfect tracee: > > > > extern "C" void _start() > > { > > __asm__ volatile ( > > "again:;" > > "int $0x03;" > > "jmp again;" > > "movl $1,%eax;" > > "xorl %ebx, %ebx;" > > "int $0x80;" > > ); > > } > > ls -al /proc/`pidof hello`/fd > > > > lrwx------ 1 prak prak 64 03-26 19:42 0 -> /dev/pts/19 > > lrwx------ 1 prak prak 64 03-26 19:42 1 -> /dev/pts/19 > > lrwx------ 1 prak prak 64 03-26 19:42 2 -> /dev/pts/19 > > lrwx------ 1 prak prak 64 03-26 19:42 3 -> /dev/ptmx > > lrwx------ 1 prak prak 64 03-26 19:42 5 -> /dev/pts/19 > > > > ls -al /proc/`pidof lldb`/fd > > > > lrwx------ 1 prak prak 64 03-26 19:43 0 -> /dev/pts/16 > > lrwx------ 1 prak prak 64 03-26 19:43 1 -> /dev/pts/16 > > lrwx------ 1 prak prak 64 03-26 19:43 2 -> /dev/pts/16 > > lrwx------ 1 prak prak 64 03-26 19:43 3 -> /dev/ptmx > > lrwx------ 1 prak prak 64 03-26 19:43 4 -> /dev/ptmx > > lr-x------ 1 prak prak 64 03-26 19:43 5 -> pipe:[1301667] > > l-wx------ 1 prak prak 64 03-26 19:43 6 -> pipe:[1301667] > > lr-x------ 1 prak prak 64 03-26 19:43 7 -> pipe:[1299830] > > l-wx------ 1 prak prak 64 03-26 19:43 8 -> pipe:[1299830] > > > > So it was spawned as usual using fork() by Linux/ProcessMonitor.cpp > > And it was given slave pts, lldb however has no '/tmp/out.txt' file > > anywhere. > > > > Should this for this case?: > > a) be passed opened to inferior before exec, or > > b) lldb should read master pty and write to /tmp/out.txt > > > > I would guess that should be a: > > > > But probably then: > > > > SetSTDIOFileDescriptor(m_monitor->GetTerminalFD()); > > > > from ProcessPosix::DoLaunch() ProcessPosix.cpp:253 after creating process > > spoils the fun. > > Also std{in,err,path)_path had to be empty here. > > > > Cheers, > > /Piotr > > > > > > 2014-03-26 19:08 GMT+01:00 Greg Clayton <[email protected]>: > > Seems like we are having some problem re-directing to terminals and files > > that exist. I would try debugging through the launch process and see who is > > doing what with file re-direction. It works on MacOSX just fine, so this is > > probably a linux only issue. Linux does fork() + exec() so some code in > > there isn't doing the right things. > > > > % lldb > > (lldb) settings set target.output-path /tmp/out.txt > > (lldb) file /bin/ls > > Current executable set to '/bin/ls' (x86_64). > > (lldb) run /tmp/ > > (lldb) Process 65933 launched: '/bin/ls' (x86_64) > > Process 65933 exited with status = 0 (0x00000000) > > (lldb) q > > > > % cat /tmp/out.txt > > launch-B6FwKk > > launch-OEyacj > > launchd-142.5fRyOk > > launchd-175.RBU3HO > > launchd-193.Asuh1k > > launchd-2701.dSHLJu > > launchd-738.U2ACnW > > out.txt > > > > % xcrun lldb > > (lldb) settings set target.output-path /tmp/out.txt > > (lldb) file /bin/ls > > Current executable set to '/bin/ls' (x86_64). > > (lldb) run / > > (lldb) Process 65940 launched: '/bin/ls' (x86_64) > > Process 65940 exited with status = 0 (0x00000000) > > (lldb) q > > lldb:/tmp % cat /tmp/out.txt > > AppleInternal > > Applications > > Library > > Network > > SWE > > System > > Users > > Volumes > > bin > > cores > > dev > > etc > > home > > mach_kernel > > net > > > > > > So this works on Darwin and needs to be fixed on Linux. > > > > Greg > > > > On Mar 25, 2014, at 7:15 AM, Eran Ifrah <[email protected]> wrote: > > > > > Hello Greg, > > > Thanks for the input. It still does not work ( I rewrote my terminal code > > > to look similar to lldb's PseudoTerminal, and it is still not working) > > > > > > To simplify things, I tried some basic things with the command line tool > > > 'lldb': > > > > > > I created a file ~/.lldbinit with the following content: > > > > > > eran@eran-linux: ~/llvm/build/bin $ cat ~/.lldbinit > > > settings set target.output-path /tmp/dbg.out > > > eran@eran-linux: ~/llvm/build/bin $ > > > > > > I then ran lldb while having tail -f /tmp/dbg.out& in another terminal to > > > see if the stdout is being redirected > > > > > > Now, this is the interesting part: > > > In the first run when the file /tmp/dbg.out was empty - the redirection > > > worked (tail showed the debuggee stdout) > > > In the second run (and later) - nothing was written to the file > > > > > > However, if I truncate the file using the below command: > > > > > > $ > /tmp/dbg.out > > > > > > and run lldb again - I see the stdout again - but same as before only for > > > the first time (i.e. as long as the file is empty the stdout was > > > redirected) > > > > > > The next thing I tried was to use a terminal name for redirection: > > > > > > - Open a new terminal and type `tty` (in my case it gave /dev/pts/19 ) > > > - Edit the ~/.lldbinit: settings set target.output-path /dev/pts/19 > > > - Start lldb and verify that the setting is set properly by running: > > > settings show target.output-path > > > - Run the program under lldb - the output is not redirected (i.e. it is > > > show in the same console where I ran lldb) > > > > > > Any ideas? > > > > > > P.S. > > > Sorry if this looks like a voodoo, but this is what I am getting here... > > > ;) > > > > > > Eran > > > > > > > > > > > > > > > > > > On Mon, Mar 24, 2014 at 6:46 PM, Greg Clayton <[email protected]> wrote: > > > Check out the PseudoTerminal class in > > > trunk/source/Utility/PseudoTerminal.cpp. > > > > > > See the function named PseudoTerminal::OpenFirstAvailableMaster(...). You > > > must call posix_openpt, grantpt, and unlockpt. I am guessing that because > > > you aren't calling grantpt and granting access to the slave you are > > > failing to be able to use the slave in your child process. > > > > > > Greg Clayton > > > > > > On Mar 23, 2014, at 11:32 AM, Eran Ifrah <[email protected]> wrote: > > > > > > > Sure, thanks for the help so far > > > > Eran > > > > > > > > > > > > On Sun, Mar 23, 2014 at 8:31 PM, Piotr Rak <[email protected]> wrote: > > > > I am sorry, but nothing obvious comes to me right now, probably you'll > > > > need to wait for Monday, when people more familiar with lldb will be > > > > able to help you debug this problem. > > > > > > > > > > > > 2014-03-23 16:07 GMT+01:00 Eran Ifrah <[email protected]>: > > > > > > > > > > > > > > > > > > > > On Sun, Mar 23, 2014 at 4:29 PM, Piotr Rak <[email protected]> wrote: > > > > Sorry I misinformed you about posix_spawn - it is not true for Linux > > > > and FreeBSD at least, it will use ordinary fork. > > > > > > > > > > > > 2014-03-23 15:23 GMT+01:00 Piotr Rak <[email protected]>: > > > > > > > > > > > > Hi, > > > > > > > > 2014-03-23 14:04 GMT+01:00 Eran Ifrah <[email protected]>: > > > > > > > > Thanks for your pointer Piotr. Here is the code I am using to open a > > > > pseudo-terminal (there is the UI part, which I left out): > > > > > > > > char __name[128]; > > > > memset(__name, 0, sizeof(__name)); > > > > > > > > int master(-1); > > > > m_slave = -1; > > > > if(openpty(&master, &m_slave, __name, NULL, NULL) != 0) > > > > return wxT(""); > > > > > > > > // disable ECHO > > > > struct termios termio; > > > > tcgetattr(master, &termio); > > > > termio.c_lflag = ICANON; > > > > termio.c_oflag = ONOCR | ONLRET; > > > > tcsetattr(master, TCSANOW, &termio); > > > > > > > > m_tty = wxString(__name, wxConvUTF8); > > > > > > > > At the end, m_tty contains a string name (e.g. /dev/pts/19 ). > > > > Note that the above code works flawlessly when using it with gdb (i.e. > > > > if I pass this "/dev/pts/19" to gdb's switch -tty=/dev/pts/19 I will > > > > get all the inferior output/err/input to my internal terminal) > > > > > > > > However, doing the same with LLDB (using C++ API not the command line , > > > > i.e. passing "/dev/pts/19" as an argument to SBTarget::Launch(...)) I > > > > get nothing as output... > > > > > > > > Looks sane to me. > > > > > > > > Also, I am not sure I am following the idea behind replacing the > > > > "Launch" function with my own fork(), looking at the code of Launch() > > > > suggests that it does more than a simple fork... > > > > > > > > > > > > That was my idea to debug issue if nothing else helps. > > > > Or rather bisect on which side it really is, sorry if I did not make it > > > > clear... > > > > So I was trying suggest replacing SBTarget::Launch with fork, write to > > > > child stdout/err, and see if that works alone.... > > > > > > > > SBTarget::Launch is usually actually posix_spawn right now, it uses > > > > posix_spawnattr_addopen to open descriptors for your specified paths, > > > > and should open it 3 times - given current implementation - even it is > > > > just one file. > > > > > > > > Have you inspected SBProcess and SBError returned by SBTarget::Launch? > > > > > > > > I checked IsValid() on both and its OK for both. I can actually run > > > > "next" Continue etc and seems to be working. Its just that I can't seem > > > > to redirect the stdout/err to my own console. > > > > > > > > > > > > Do you see your inferior process is indeed launching, just not > > > > displaying anything? > > > > Yes, ps -ef shows the debugee > > > > > > > > Do you have an option to check if those terminals are actually being > > > > opened (like examining /proc/<pid>/fd for linux)? > > > > The terminal is opened. Like I mentioned in my previous email, using > > > > the _same_ code with gdb works > > > > I also have a standalone terminal application which I wrote which is > > > > also using the same set of classes all of the are working for couple of > > > > years now without any problems > > > > > > > > I also tried this: > > > > I typed in my konsole 'tty' and used that as the input for Launch - it > > > > also seems to have no effect > > > > > > > > > > > > > > > > Good luck, > > > > /Piotr > > > > > > > > Any more hints? > > > > Eran > > > > > > > > > > > > > > > > On Sat, Mar 22, 2014 at 9:36 PM, Piotr Rak <[email protected]> wrote: > > > > Hi, > > > > > > > > It should. > > > > Have you opened master pseudoterminal like?: > > > > > > > > int fd = posix_openpt(flags); // open("/dev/ptmx") might work here too > > > > but less portable; > > > > grantpt(fd); > > > > unlockpt(fd); > > > > > > > > Depending on target you might need some bizarre ioctls here, but > > > > assuming you are using Linux/FreeBSD/MacOSX > > > > you should be fine. > > > > > > > > If you had already master pseudo-terminal file descriptor you can skip > > > > steps above. > > > > > > > > You can use ptsname for master file descriptor it will return you name > > > > of slave pseudo-terminal for your master. > > > > Later you can pass name returned by ptsname(fd) as Launch arguments. > > > > > > > > If above won't work you can try replacing Launch() call with ordinary > > > > fork, and in child process: > > > > > > > > slavefd = open(slavename, O_RDWR); > > > > > > > > dup2(0, slavefd); > > > > dup2(1, slavefd); > > > > dup2(2, slavefd); > > > > > > > > And see if that works alone for you... > > > > > > > > Good luck, > > > > /Piotr > > > > > > > > > > > > 2014-03-22 19:29 GMT+01:00 Eran Ifrah <[email protected]>: > > > > Hello, > > > > > > > > I am trying to use the C++ API with good success so far. > > > > I am now at a point where I want to redirect stdin/out/err of the > > > > inferior to my application (my application creates a separate pseudo > > > > terminal window) > > > > > > > > Looking at the SBTarget::Launch, I thought that simply passing > > > > "/dev/pts/<some-number>" as the 3rd, 4th and 5th argument will do the > > > > trick .. well, it did not. > > > > I am missing something basic here, can anyone shed some light please? > > > > or give an example (better) of how to achieve this? > > > > > > > > Thanks! > > > > > > > > -- > > > > Eran Ifrah > > > > Author of codelite, a cross platform open source C/C++ IDE: > > > > http://www.codelite.org > > > > wxCrafter, a wxWidgets RAD: http://wxcrafter.codelite.org > > > > > > > > _______________________________________________ > > > > lldb-dev mailing list > > > > [email protected] > > > > http://lists.cs.uiuc.edu/mailman/listinfo/lldb-dev > > > > > > > > > > > > > > > > > > > > > > > > -- > > > > Eran Ifrah > > > > Author of codelite, a cross platform open source C/C++ IDE: > > > > http://www.codelite.org > > > > wxCrafter, a wxWidgets RAD: http://wxcrafter.codelite.org > > > > > > > > > > > > > > > > > > > > > > > > -- > > > > Eran Ifrah > > > > Author of codelite, a cross platform open source C/C++ IDE: > > > > http://www.codelite.org > > > > wxCrafter, a wxWidgets RAD: http://wxcrafter.codelite.org > > > > > > > > > > > > > > > > > > > > -- > > > > Eran Ifrah > > > > Author of codelite, a cross platform open source C/C++ IDE: > > > > http://www.codelite.org > > > > wxCrafter, a wxWidgets RAD: http://wxcrafter.codelite.org > > > > _______________________________________________ > > > > lldb-dev mailing list > > > > [email protected] > > > > http://lists.cs.uiuc.edu/mailman/listinfo/lldb-dev > > > > > > > > > > > > > > > -- > > > Eran Ifrah > > > Author of codelite, a cross platform open source C/C++ IDE: > > > http://www.codelite.org > > > wxCrafter, a wxWidgets RAD: http://wxcrafter.codelite.org > > > > > > > > > > > > -- > Eran Ifrah > Author of codelite, a cross platform open source C/C++ IDE: > http://www.codelite.org > wxCrafter, a wxWidgets RAD: http://wxcrafter.codelite.org > > > > -- > Eran Ifrah > Author of codelite, a cross platform open source C/C++ IDE: > http://www.codelite.org > wxCrafter, a wxWidgets RAD: http://wxcrafter.codelite.org _______________________________________________ lldb-dev mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/lldb-dev
