Professional Web Applications Themes

OSR505 Signal trapping in shell scripts - SCO

My apologies if this is insufficiently SCO specific :-) I'm trying to get ain interactive script to clean up temporary files when a terminal disconnects (telnet in this case). My test script is at the end. Here's what I get when I press the Interrupt key (stty intr) 2003-09-30 15:15:07 : Trapped signal INT 2003-09-30 15:15:07 : Trapped signal Normal Exit Here's what I get when I abruptly disconnect my terminal (exit telnet client) 2003-09-30 15:15:28 : Trapped signal HUP 2003-09-30 15:15:28 : Trapped signal Normal Exit 2003-09-30 15:15:28 : Trapped signal HUP A file that should be deleted in ...

  1. #1

    Default OSR505 Signal trapping in shell scripts

    My apologies if this is insufficiently SCO specific :-)

    I'm trying to get ain interactive script to clean up temporary files
    when a terminal disconnects (telnet in this case).

    My test script is at the end.

    Here's what I get when I press the Interrupt key (stty intr)
    2003-09-30 15:15:07 : Trapped signal INT
    2003-09-30 15:15:07 : Trapped signal Normal Exit

    Here's what I get when I abruptly disconnect my terminal (exit telnet
    client)
    2003-09-30 15:15:28 : Trapped signal HUP
    2003-09-30 15:15:28 : Trapped signal Normal Exit
    2003-09-30 15:15:28 : Trapped signal HUP

    A file that should be deleted in a signal trap still exists (see script).

    Q: Why isnt my "rm" working and why is HUP recorded twice?


    Script trapint.ksh:
    \/\/\/\/\/\/\/\/\/\/\/\/\/\/
    #!/bin/ksh

    #
    # create a record of the existence of this process
    #
    echo $$ > trapint.pid

    #
    # trap interrupts etc
    #
    function exithandler {
    mysignal=$1
    echo `date "+%Y-%m-%d %H:%M:%S"` \
    ": Trapped signal $1 " >> trapint.log
    rm trapint.pid >> trapint.log 2>&1
    }
    function traphandler {
    mysignal=$1
    echo `date "+%Y-%m-%d %H:%M:%S"` \
    ": Trapped signal $1 " >> trapint.log
    exit
    }
    #
    # set traps individually
    #
    trap 'exithandler "Normal Exit" ' 0
    trap 'traphandler "HUP" ' 1
    trap 'traphandler "INT" ' 2

    #
    # invoke app
    #
    perl -e 'print "Enter: "; $ans=<>; print "\n<==$ans\n";'

    result=$?
    echo "Shell sees result as $result"

    exit
    \/\/\/\/\/\/\/\/\/\/\/\/\/\/


    --
    Ian Wilson.
    Glad that Swen.A is slowly abating!

    Ian Guest

  2. #2

    Default Re: OSR505 Signal trapping in shell scripts

    Ian Wilson wrote:
     

    Can't tell if it is or isn't, but certainly it's a _programming_
    question...
     

    I tested this in the same way: exiting telnet client. This might be
    significant.

    I learned a bunch of things, can't say I know _exactly_ what's going on,
    but at least there are workarounds.

    The proximate cause of not removing trapint.log is that your `rm`
    command is receiving a SIGHUP. Oddly, if I change it to `rm -f` then it
    does not receive a SIGHUP. I verified this with both `trace` and
    `truss`.

    One workaround is to put at the top of exithandler():

    trap "" 1 # ignore SIGHUP from now on

    I thought this might be due to ksh's complex process handling, so I
    tried with the Bourne shell. Besides the "#!/bin/ksh", I had to change
    the function declarations to the "exithandler() { ..." style. Your real
    program probably has other Korn-isms in it, but the test code worked
    under Bourne. It also behaved exactly the same, which was a surprise to
    me.

    I then changed the kernel parameter SECSTOPIO to 0 (I did so as follows
    -- live kernel brain surgery, albeit very simple:

    # scodb -w
    scodb> sec_stopio=0
    scodb> q

    ) -- and the problem went away. So this is an interaction with
    stopio(S). `telnetd` calls stopio() on the tty you were logged in on.
    This is a more persistent source of SIGHUPs than a mere hangup. If you
    were running the script on a serial terminal on which you had _not_
    logged in, merely opened the modem-control port and ran the script --
    then the problem wouldn't exist. If you had logged in then it probably
    would, because `login` or `init` would stopio() the port.

    You didn't say what release of OSR5 you're using. I'm on 507. This
    behavior was actually must worse in the past (502 and earlier); on those
    releases, you would get a SIGHUP _every_ time you tried to access a file
    descriptor on which stopio() had been called. Starting in 504, a
    process only gets one SIGHUP per fd.

    The question remains, what was `rm` doing to that fd which provoked a
    SIGHUP? Checking the source... I see this:

    if ((!fflag && isatty(0)) || iflag) {
    /* then look up the localized regular expression for "yes" */

    Kind of a silly code path. It knows that `rm -i`, and `rm` without "-f"
    _when on an interactive terminal_, is potentially going to ask
    questions. Not that it _is_, only potentially. isatty(0) is going to
    end up doing ioctl()s on fd 0, which is your stopio()'d telnetd pty.
    Thus, doom.

    The workaround of doing "trap '' 1" will protect _anything_ you run out
    of the exit function. You could also specifically protect `rm` by doing

    rm trapint.pid >> trapint.log 2>&1 < /dev/null

    .... but that's much shakier, depends on information from inside SCO's
    `rm` source code that could change without your knowledge.

    So...

    Various workarounds (choose 1):

    # at top of exit function: ignore SIGHUP
    trap "" 1

    # at top of exit function: close dangerous descriptors
    exec </dev/null >/dev/null 2>&1 # at top of exit function

    # protect just the rm command itself:
    rm trapint.pid >> trapint.log 2>&1 < /dev/null

    # disable stopio(S) system-wide:
    cd /etc/conf/cf.d
    ./configure
    "8" ... and set SECSTOPIO to 0
    # then relink, reboot
     

    So, turned out to be very OpenServer-specific. I understand that HP-UX
    also has SecureWare stuff in it, but knowing how many years of drift we
    have between the two implementations, I doubt the issues are similar.
    Plus, it was enhanced by a specific silliness in OSR5 `rm`.

    But... regarding that specific silliness: it's only silly because you
    might have expected `rm` not to touch the tty. Contrast to some other
    code you might have in your exit function:

    echo Bailing! # the shell writes to stdout and is SIGHUP'd
    cat exit.msg # `cat` writes to stdout and is SIGHUP'd
    stty -a > trapint.exit-stty-settings # ioctl(stdin) and is SIGHUP'd

    I still don't know precisely why the _shell_ saw SIGHUP twice (thus
    entered traphandler() twice). I can speculate a bit, but haven't set up
    the detailed tests to confirm this. I'm guessing that the shell might
    not have received a SIGHUP from telnetd directly; `perl` did because it
    was in the middle of an I/O when telnetd exited. So the perl statement
    ended, and the shell tried to do:

    echo "Shell sees result as $result"

    which would write to stdout, so it goes a SIGHUP relating to the
    stopio'd fd 1. Then it got into the trap handler and then the exit
    handler. The exit handler ran `rm` as:

    rm trapint.pid >> trapint.log 2>&1

    This involves _closing_ fds 1 and 2 (in the process of reopening them to
    "trapint.log"). I'm pretty sure the close(S) system call isn't
    sensitive to stopio(), but suppose the shell does something else on the
    way out. Maybe it flushes a stdio buffer; maybe it attempts an ioctl()
    to see what sort of file it's closing. When it does these things to fd
    1, nothing special happens (it's already been SIGHUP'd for fd 1). When
    it does them to fd 2, kaboom.

    .... untested theory.
     
     
    Bela Guest

  3. #3

    Default Re: OSR505 Signal trapping in shell scripts

    Wow - thanks Bela, problem solved.

    further unimportant and skippable ramblings added below.

    Bela Lubkin wrote: 
    >
    >
    > Can't tell if it is or isn't, but certainly it's a _programming_
    > question...
    >

    >
    >
    > I tested this in the same way: exiting telnet client. This might be
    > significant.
    >
    > I learned a bunch of things, can't say I know _exactly_ what's going on,
    > but at least there are workarounds.
    >
    > The proximate cause of not removing trapint.log is that your `rm`
    > command is receiving a SIGHUP. Oddly, if I change it to `rm -f` then it
    > does not receive a SIGHUP. I verified this with both `trace` and
    > `truss`.
    >
    > One workaround is to put at the top of exithandler():
    >
    > trap "" 1 # ignore SIGHUP from now on[/ref]

    Thats what I used - thanks.
     

    My real script started out as a C shell script, onintr is too limiting.
    Yes I've read "CSH programming considered harmful" but I kinda got
    pushed into it. Normally I use Korn shell.

    My Kornised real script actually went into a near infinite loop of
    SIGHUPs until it seemed to run out of resources. Your explanation of
    STOPIO accounts for how my attempt at signal trapping and use of IO
    caused this.
     

    OpenServer 5.0.5 - pending an upgrade to 5.0.7.
     

    I chose that one. Its also hinted at in various books I had consulted.
     
     
    >
    >
    > So, turned out to be very OpenServer-specific. I understand that HP-UX
    > also has SecureWare stuff in it, but knowing how many years of drift we
    > have between the two implementations, I doubt the issues are similar.
    > Plus, it was enhanced by a specific silliness in OSR5 `rm`.
    >
    > But... regarding that specific silliness: it's only silly because you
    > might have expected `rm` not to touch the tty. Contrast to some other
    > code you might have in your exit function:
    >
    > echo Bailing! # the shell writes to stdout and is SIGHUP'd
    > cat exit.msg # `cat` writes to stdout and is SIGHUP'd
    > stty -a > trapint.exit-stty-settings # ioctl(stdin) and is SIGHUP'd[/ref]

    Yep.
     

    Well, I certainly feel I already got more than my money's worth :-)

    Five stages of usenet posting:
    Frustration
    Composition
    Expectation
    Impatience
    Joy
     
    >
    > [/ref]

    Ian Guest

  4. #4

    Default Re: OSR505 Signal trapping in shell scripts

    Ian Wilson wrote:
     
     [/ref]
     

    Hmmm, that's odd. It shouldn't have gone into an infinite loop of
    SIGHUPs because stopio() should only have sent one per file descriptor
    per process. Sending an infinite stream (that is, one for each I/O
    attempt) was an OSR502 behavior, fixed in 504.
     
    >
    > OpenServer 5.0.5 - pending an upgrade to 5.0.7.[/ref]
     
    Bela Guest

Similar Threads

  1. shell scripts and cron
    By TB in forum Linux / Unix Administration
    Replies: 2
    Last Post: February 7th, 05:10 AM
  2. [ANN] Protect you Unix Shell Scripts!
    By Bungisoft, in forum Linux Setup, Configuration & Administration
    Replies: 6
    Last Post: December 2nd, 10:48 PM
  3. [ANN] Protect you Unix Shell Scripts!
    By Bungisoft, Inc. in forum Linux / Unix Administration
    Replies: 3
    Last Post: November 9th, 02:43 PM
  4. [ANN] Protect you Unix Shell Scripts!
    By Bungisoft, in forum UNIX Programming
    Replies: 3
    Last Post: November 9th, 02:43 PM
  5. Timers in shell scripts
    By Chris in forum Mac Programming
    Replies: 3
    Last Post: November 7th, 07:28 PM

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139