lldb - How do I kill commands stuck in infinite loops - xcode

Simple question, but I can't seem to find the answer anywhere online and it's really frustrating.
Suppose I have this buggy code I'm trying to debug:
int myBug()
{
while(1);
return 0;
}
If I'm debugging this with LLDB and type print myBug() I get no result, ever (no surprises). However this means I can no longer debug because LLDB is stuck and cannot continue. Is there a way to kill the print myBug() command? So far the only workaround is quitting and restarting everything -- far from convient.
I'm using LLDB in Xcode 4.6.1 and I've trying a bunch of keystrokes like Ctrl+C, Ctrl+T, but nothing seems to work :(

Yeah, from within Xcode there isn't an easy way to interrupt this expression evaluation. If you're using command-line lldb, control-C will work as expected. You can send a signal to your process, killall -INT appname. You can give lldb a timeout for an expression evaluation, expressed in microseconds, so a five second timeout calling myBug() looks like
(lldb) expr -t 5000000 -- myBug()
error: Execution was interrupted, reason: breakpoint 1.1.
The process has been returned to the state before expression evaluation.
(lldb)
You can file a bug report about this on Xcode at http://bugreport.apple.com/ if this is something that comes up in your workflow.

Related

Debug slow bash after executing command

Bash randomly hangs for a few seconds after executing a command. At that stage, Ctrl+C or anything just gets printed on the terminal.
I use tmux, so I had already opened up htop to view resource usage in a different pane. All was fine. Also, when it is hung, moving to other panes works fine, I can type anything, but it hangs up when I press Enter. All of the panes execute as soon as the first pane which was hung continues. The point being resources are not a bottleneck.
I tried to use set -x in bash to check if something is happening, but due to unpredictable hangs, I had to revert it back to keep working sanely.
I also looked up How to profile a bash shell script slow startup?, but I can't find a way in there, to find slow bash after executing a command.
Any ideas how do I debug it? I am slowly going mad.
Edit: To add more context, the hang varies from 5 seconds to a minute.
To give an example, consider this:
$ ls
<--- hangs here
// after a few seconds, it continues
file1.txt
<--- never hangs here, after executing the cmd
$
And this is just an example, nothing to do with ls. I find no correlation to any particular command by which I can reproduce this.

Using DTrace to get stack traces / profiling data on Rust

I'm trying to get a nice flamegraph of my Rust code. Unfortunately, Xcode 8.3 doesn't support exporting profiling data anymore, so I've been trying to use DTrace to get the profiling data.
I have enabled debug info in my Cargo.toml for the release binaries:
[profile.release]
debug = true
Then I run the release binary (mybinaryname), and sample stack traces using DTrace:
sudo dtrace -n 'profile-997 /execname == "mybinaryname"/ { #[ustack(100)] = count(); }' -o out.user_stacks
The end result is something like this:
0x10e960500
0x10e964632
0x10e9659e0
0x10e937edd
0x10e92aae2
0x10e92d0d7
0x10e982c8b
0x10e981fc1
0x7fff93c70235
0x1
1
For comparison, getting traces of iTerm2 gets me nice traces like this:
CoreFoundation`-[__NSArrayM removeAllObjects]
AppKit`_NSGestureRecognizerUpdate+0x769
CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__+0x17
CoreFoundation`__CFRunLoopDoObservers+0x187
CoreFoundation`__CFRunLoopRun+0x4be
CoreFoundation`CFRunLoopRunSpecific+0x1a4
HIToolbox`RunCurrentEventLoopInMode+0xf0
HIToolbox`ReceiveNextEventCommon+0x1b0
HIToolbox`_BlockUntilNextEventMatchingListInModeWithFilter+0x47
AppKit`_DPSNextEvent+0x460
AppKit`-[NSApplication(NSEvent) _nextEventMatchingEventMask:untilDate:inMode:dequeue:]+0xaec
AppKit`-[NSApplication run]+0x39e
AppKit`NSApplicationMain+0x4d5
iTerm2`main+0x6e
libdyld.dylib`start+0x1
iTerm2`0x1
1
Is it possible to get stack traces with debug info in Rust code? (Xcode's Instruments for sure can see the function names, so they are there!) If it is possible, do I need to do take some additional steps, or am I just doing something wrong?
I found a workaround and got some insight why it might not have worked, but the reason why is not 100% clear.
The debug symbols that rustc produces can be found in target/release/deps/mybinaryname-hashcode.dSYM. In the same directory there is a binary file target/release/deps/mybinaryname-hashcode to which the symbols correspond to.
The debug symbol finding library on MacOS is highly magical – as is mentioned in the LLDB docs, symbols are found using various methods, including Spotlight search. I'm not even sure which Frameworks are the ones being used by Xcode's Instruments and the bundled DTrace. (There are mentions about frameworks called DebugSymbols.framework and CoreSymbolication.framework.) Because of this magic, I gave up trying to understand why didn't it work.
The workaround is to pass dtrace the -p option along with the PID of the inspected process:
sudo dtrace -p $PID -n 'profile-997 /pid == '$PID'/ { #[ustack(100)] = count(); }' -o $TMPFILE &>/dev/null
Here's the man of -p:
Grab the specified process-ID pid, cache its symbol tables, and exit upon its completion. If more than one -p option is present on the command line, dtrace exits when all commands have exited, reporting the exit status for each process as it terminates. The first process-ID is made available to any D programs specified on the command line or using the -s option through the $target macro variable.
It's not clear why the debug info of various other binaries is shown by default, or why Rust binaries need the -p option, but it does its job as a workaround.

Tcl on osx: Open pipe for reading: No `readable` event generated on EOF

I'll try to be specific. This is OSX-Yosemite, Tcl 8.5.9. I'm doing something like that:
set fd [open "|$external"]
fconfigure $fd -blocking 0 -buffering line
fileevent $fd readable "set $tracername $fd"
This tracername holds the name of a global variable (with ::namespace-based name), which is next used here:
# Ok, now clear the variable
set $tracername ""
# If vwait causes error, it may happen that the process
# has finished before it could be added to the event list
# (just the script had no opportunity to see it). If this
# happens, just go on, and in the next roll you'll find it out anyway.
$mkv::debug "--- Waiting for an event from any of fileevent-registered processes ($tracername)..."
catch {vwait $tracername}
$mkv::debug "--- UNBLOCKED BY: $tracername=[set $tracername]"
This works perfectly on Linux and Cygwin. On Mac it stalls on vwait (to the best of my knowledge).
This catch is here added just for a case when all "files" from the fileevent have been closed - according to the documentation, doing vwait when no events were scheduled results in exception of type error (to prevent waiting forever). However I doubt this is the case here because the command started is a C++ compiler command call that takes at least more than half a second to run.
The program is a Tcl version of make tool and this code is a part of parallel build support. This happens when I run without parallel support. If I run at least 2 process simultaneously, everything works fine.
What I observe when debugging is that the child process spawned by open |$external stops printing anything on the output, so looxlike it has finished. But normally I have a readable event generated, which gives me opportunity to check if [eof $fd] and close it.

Let a program run x seconds but preserve the ability to control-C

I'm looking for a way to run a script for x seconds with still the possibility to interrupt it before those x seconds are past.
If I didn't need the ability to Ctrl-C I'd write
./my_script &
sleep $x
kill $!
But here if I Ctrl-C during the script the fork keeps running.
I kinda know how to kill the script if launched in a sub-shell:
trap "echo sub-script terminated" INT
(./my_script)
trap - INT
but I do not know how to transpose that to a fork (I do not get clearly the differences between the two concepts I have to admit).
EDIT: I'd like to know how portable are the solutions btw, if you can mention that in your answers, that'd be of great value to me.
timeout $x ./my_script
If you have a reasonably new GNU Coreutils, timeout is included there. Before, there used to be a number of slightly incompatible timeout variants from different sources (the one I have in most places comes from the Postfix distribution originally IIRC).
If you don't have timeout for your distro, there are many shell and Perl hacks out there.

TCL hangs when trying to close TCL pipe

When launching tclsh and typing this:
close [open "|tclsh" w]
it works fine.
But, when in ~/.tclshrc you have package require Tk, the same line makes tclsh to HANG!
The same issue is with all GUI packages like Tk, Itk, Img, Iwidgets, however with not GUI packages like Itcl, it worsk fine.
How can I fix this issue? The point is to make tclsh not to hang, when typing close [open "|tclsh" w] with package require Tk in ~/.tclshrc.
The same issue is with wish. close [open "|wish" w] makes wish to HANG (with an empty ~/.wishrc file)!
I got this issue on both 32 and 64 bit CentOS.
I have the following versions of packages: tcl-8.5.8, tk-8.5.8, img-1.3, itcl-3.4.b1, itk-3.3, iwidgets-4.0.1.
Tcl applications mostly exit when they have finished their script, whether or not it is provided interactively. However the Tk package changes things around so that when the end of the script is reached, it instead goes into a loop handling events. If you're relying on an end-of-file causing things to exit, that's going to look a lot like a hang, but really it's just waiting properly for the GUI app to finish (so it can report the exit status of the subprocess).
The fix is to make a channel-readable event handler for stdin in the subprocess. There's a few ways to do this in detail, but here's a simple one that can go at the end of the bulk of code that you normally send:
proc ReadFromStdin {} {
if {[gets stdin line] >= 0} {
uplevel "#0" $line
} elseif {[eof stdin]} {
exit
} else {
# Partial read; try later when rest of data available
}
}
fileevent stdin readable ReadFromStdin
This assumes that each line is a full executable command; that might not be true, of course, but writing the code to use info complete to compose lines is less clear and possibly unnecessary here. (You know what you're actually sending better than I…)
My thought would be that it's waiting for wish to finish running, as per the man page:
If channelId is a blocking channel for
a command pipeline then close waits
for the child processes to complete.
Since wish enters an infinite loop (the event loop) and never exits, the close command will hang. Along the same lines, [package require Tk] (I believe) starts the event loop, so will cause the same behavior.
I'll admit though that it's loading .tclshrc at all, since
If there exists a file .tclshrc (or tclshrc.tcl on the Windows platforms) in the home directory of the user, interactive tclsh evaluates the file as a Tcl script just before reading the first command from standard input.
It seems odd to me that [open "|tclsh" w] winds up in an interactive shell.
As a side note, [pacakge require Tk] seems like a really strange thing to do in .tclshrc. In theory, you won't always want Tk (the window and event loop) when running Tcl (ie, command line only apps)... and, when you do want it, you know you do. To each their own, I suppose, it just seems odd to me.

Resources