Prevent sigint from closing OpenOCD when using OpenOCD with GDB - shell

I am trying to write a script to launch OpenOCD in the background, and then launch and instance of GDB connected to my OpenOCD server. This mostly works, except that as soon as I type the interrupt character to halt the target I am debugging my OpenOCD server exits. It appears that OpenOCD is receiving SIGINT.
I have tried to separate OpenOCD from GDB in a number of different ways, at this point my script looks like this:
#! /bin/sh
trap '' SIGINT && nohup sh -c "trap '' SIGINT & openocd -f openocd-jlink.cfg < /dev/null" &
OPENOCD_PID=$!
arm-none-eabi-gdb -ex "set architecture armv6-m" -ex "target extended-remote localhost:2331" obj/main.elf
kill $OPENOCD_PID
I'm pretty sure that this should be very overkill yet OpenOCD still exits as soon as I type the interrupt character in GDB. If I run the same commands directly from my shell (not as part of script) everything works as expected. It works even if I just run openocd -f openocd-jlink.cfg & followed by GDB, no separate shell, nohup or trapping of SIGINT is required.
I'm hoping that someone might have an idea of what I can do in my script to prevent the SIGINT in GDB from reaching OpenOCD. Maybe there is some way to daemonize entirely from shell? I have read a lot of answers here about more generic issues with SIGINT in scripts, so I have a feeling this might be something specific to OpenOCD and GDB.

I have managed to solve this issue by using setsid. The working version of the script is:
#! /bin/sh
setsid openocd -f openocd-jlink.cfg -l /dev/null &
arm-none-eabi-gdbm" -ex "target extended-remote localhost:2331" obj/main.elf
killall openoc
Since I want the script to work on macOS as well as Linux and macOS does not ship with a setsid I ended up using Python to launch OpenOCD, which looks like this:
subprocess.Popen(["openocd", "-f", "openocd-jlink.cfg", "-l", "/dev/null"], preexec_fn = os.setsid)

Related

Close a Terminator terminal opened from bash when the program in it exits

I have a udev rule that calls a script whenever I insert a certain USB device. That script launches a terminal using the following command:
terminator -e "...some_program" & exit
(Could have also been xterm, doesn't matter as far as I can tell.)
Once 'some_program' finishes doing what it should, it exits (from inside that program, not the bash), but the terminator terminal remains open, unless I Ctrl+C it, in which case it closes. But I don't want to Ctrl+C it, that's the whole point.
I have another udev rule that operates when the USB device is removed. But that rule won't trigger until the terminal that was opened from the
'insert usb rule' closes (even though I used & exit after launching the script from the 'insert usb rule')
I don't have anymore ideas and I've searched high and low for a solution. But nothing worked.
I tried sending SIGINT from inside some_program instead of using exit(1), it didn't work. The program terminated, but the terminal stayed open.
I tried killing the terminal by getting its PID and killing it. It didn't work.
I tried opening another terminal and killing the PID from there, it didn't work.
You might want to try this:
terminator -e "bash -c 'yourcommand'"
At least when I call ls this way it automatically closes:
# this closes automatically:
terminator -e "bash -c 'ls'"
# to test, this closes when the less command is ended (eg. by hitting q):
terminator -e "bash -c 'ls | less'"
Apparently terminator doesn't initialize it's own shell this way and as soon as the command passed with the -c option ends, the shell is terminated and terminator automatically closes the window.
Solved it. no need use 'bash -c'.
'some_program' is a ROS node, so all i needed to do is kill the rosmaster...
$ killall -9 rosmaster
and it works now.

Enter Shell Of already Running gdb

I have gdb running on cpp application process on remote machine, and accidenttly close terminal. How do i get into this gdb shell again?
$ pidof application
12345
$ pidof gdb
23456
gdb was started like "gdb --pid=12345" which is attached to process.
How do I get back into gdb shell from external shell. Is there any way like
"enter-gdb-shell with pid 23456"
reptyr does what you want: attach a terminal to a running process.

Inhibit SIGINT for the process in group

I have a bash script, which start 2 processes:
openocd ...flags... 2>openocd.log &
arm-none-eabi-gdb
When in gdb, interrupting execution with Ctrl+C causes openocd to receive SIGINT as well and, thus it stops. I've tried to trap and reissue SIGINT directly to gdb with:
trap 'kill 2 $!' INT
But apart from requiring root, it does not work anyway:
./dbg.sh: 1: kill: No such process
Are there elegant ways to perform the task?
__
Well, running script with debug options on helped a lot. But still I encounter weird behavior. Here is the content of my script:
#!/bin/sh
set -vx
trap 'killall -s2 arm-none-eabi-gdb-py' 2
openocd -f ...flags... 2>openocd.log & arm-none-eabi-gdb-py
When I run killall -s2 arm-none-eabi-gdb-py from within different tty - it terminates execution of remote target and does not close openocd, but sending SIGINT through Ctrl+C returns:
+ killall -s2 arm-none-eabi-gdb-py
arm-none-eabi-gdb-py: no process found
Seems like trap does not inhibit signals at all... changing to trap 'ps -ef' INT reveals, openocd AND gdb are already down when the trap command executes.
Isn't there a missing '&' in your instruction (it would give that)?
openocd -f ...flags... 2>openocd.log &**&** arm-none-eabi-gdb-py

Tcl and Cygwin and a Background Process which should hangup

I have a bash script server.sh which is maintained by an external source and ideally should not be modified. This script writes to stdout and stderr.
In fact, this server.sh itself is doing an exec tclsh immediately:
#!/bin/sh
# \
exec tclsh "$0" ${1+"$#"}
so in fact, it is just a wrapper around a Tcl script. I just mention this in case you think that this matters.
I need a Tcl script setup.tcl which is supposed to do some preparatory work, then invoke server.sh (in the background), then do some cleanup work (and display the PID of the background process), and terminate.
server.sh is supposed to continue running until explicitly killed.
setup.tcl is usually invoked manually, either from a Cygwin bash shell or from a Windows cmd shell. In the latter case, it is ensured that Cygwin's bash.exe is in the PATH.
The environment is Windows 7 and Cygwin. The Tcl is either Cygwin's (8.5) or ActiveState 8.4.
The first version (omitting error handling) went like this:
# setup.tcl:
# .... preparatory work goes here
set childpid [exec bash.exe server.sh &]
# .... clean up work goes here
puts $childpid
exit 0
While this works when started as ActiveState Tcl from a Windows CMD shell, it does not work in a pure Cygwin setup. The reason is that as soon as setup.tcl ends, a signal is sent to the child process and this is killed too.
Using nohup would not help here, because I want to see the output of server.sh as soon as it occurs.
My next idea would be to created an intermediate bash script, mediator.sh, which uses disown -h to detach the child process and keep it from being killed:
#!/usr/bin/bash
# mediator.sh
server.sh &
child=$!
disown -h $child
and invoke mediator.sh from setup.tcl. But aside from the fact that I don't see an easy way to pass the child PID up to setup.tcl, the main problem is that it doesn't work either: While mediator.sh indeed keeps the child alive when called from the Cygwin command line directly, we have the same behaviour again (server.sh being killed when setup.tcl exits), when I call it via setup.tcl.
Anybody knowing a solution for this?
You'll want to set a trap handler in your server script so you can handle/ignore certain signals.
For example, to ignore HUP signals, you can do something like the following:
#!/bin/bash
handle_signal() {
echo "Ignoring HUP signal"
}
trap handle_signal SIGHUP
# Rest of code goes here
In the example case, if the script receives a HUP signal it will print a message and continue as normal. It will still die to Ctrl-C as that's the INT signal which is unhandled.

Bash script that will survive disconnection, but not user break

I want to write a bash script that will continue to run if the user is disconnected, but can be aborted if the user presses Ctrl+C.
I can solve the first part of it like this:
#!/bin/bash
cmd='
#commands here, avoiding single quotes...
'
nohup bash -c "$cmd" &
tail -f nohup.out
But pressing Ctrl+C obviously just kills the tail process, not the main body. Can I have both? Maybe using Screen?
I want to write a bash script that will continue to run if the user is disconnected, but can be aborted if the user presses Ctrl+C.
I think this is exactly the answer on the question you formulated, this one without screen:
#!/bin/bash
cmd=`cat <<EOF
# commands here
EOF
`
nohup bash -c "$cmd" &
# store the process id of the nohup process in a variable
CHPID=$!
# whenever ctrl-c is pressed, kill the nohup process before exiting
trap "kill -9 $CHPID" INT
tail -f nohup.out
Note however that nohup is not reliable. When the invoking user logs out, chances are that nohup also quits immediately. In that case disown works better.
bash -c "$cmd" &
CHPID=$!
disown
This is probably the simplest form using screen:
screen -S SOMENAME script.sh
Then, if you get disconnected, on reconnection simply run:
screen -r SOMENAME
Ctrl+C should continue to work as expected
Fact 1: When a terminal (xterm for example) gets closed, the shell is supposed to send a SIGHUP ("hangup") to any processes running in it. This harkens back to the days of analog modems, when a program needed to clean up after itself if mom happened to pick up the phone while you were online. The signal could be trapped, so that a special function could do the cleanup (close files, remove temporary junk, etc). The concept of "losing your connection" still exists even though we use sockets and SSH tunnels instead of analog modems. (Concepts don't change; all that changes is the technology we use to implement them.)
Fact 2: The effect of Ctrl-C depends on your terminal settings. Normally, it will send a SIGINT, but you can check by running stty -a in your shell and looking for "intr".
You can use these facts to your advantage, using bash's trap command. For example try running this in a window, then press Ctrl-C and check the contents of /tmp/trapped. Then run it again, close the window, and again check the contents of /tmp/trapped:
#!/bin/bash
trap "echo 'one' > /tmp/trapped" 1
trap "echo 'two' > /tmp/trapped" 2
echo "Waiting..."
sleep 300000
For information on signals, you should be able to man signal (FreeBSD or OSX) or man 7 signal (Linux).
(For bonus points: See how I numbered my facts? Do you understand why?)
So ... to your question. To "survive" disconnection, you want to specify behaviour that will be run when your script traps SIGHUP.
(Bonus question #2: Now do you understand where nohup gets its name?)

Resources