Search code examples
bashcygwintcl

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?


Solution

  • 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.