ksh interrupt read instruction with signal


 
Thread Tools Search this Thread
Top Forums Shell Programming and Scripting ksh interrupt read instruction with signal
# 1  
Old 11-30-2011
ksh interrupt read instruction with signal

Dear shell experts,

I spent last few days porting ksh script from ksh88/SunOS to ksh93/Linux.
Basically, things are going well and I do not have too much troubles porting ks88 script to ksh93, but I stuck on one item. It's about sending and handling the signal.
I found two similar topics on this forum, but hints provided there, do not resolve my problem (

https://www.unix.com/shell-programmin...d-command.html
https://www.unix.com/shell-programmin...t-timeout.html )

Please consider following simple script.

Code:
  #!/bin/ksh
  typeset TEXT=""
  
  trap 'echo "got a signal!"' USR1
  
  echo "put some text here.... my pid is $$"
  read TEXT
  echo "I'm done"
  
  exit 0

Run the script and hold on read instruction (do not put any data).
Now, from other terminal, send USR1 signal to this script. Please note, ksh88/SunOS and ksh93/Linux behave different way here.

# ksh88/SunOS”
[OUTPUT]
put some text here.... my pid is 11325

got a signal!
I'm done
[/OUTPUT]

# ksh93/Linux #
[OUTPUT]
put some text here.... my pid is 29688
got a signal!

# It still sits in read instruction. You need to hit entrer to continue.
[/OUTPUT]

I was expecting ksh handling the signal this way:
1. break current system call (read instrluction in this case)
2. execute trap instructions
3. continue with next instruction after the read.

This flow work on the SunOS/ksh88. Read instruction is interrupted, but not with ksh93/Linux. With ksh93/Linux I'm not able to break read instruction using signal and that's my concern here.

Please note, I can not use “-t” option for read, since my script must be backward compatible with ksh88. I either can't use “line” command, since it's not available on my linux machine.
I would appreciate any hint/suggestions how to break read instruction.
Kind Regards,
bzk
# 2  
Old 11-30-2011
Try this, lets see how it behaves , just add a 0 after USR1
Code:
trap 'echo "got a signal!"' USR1 0

Or better yet, try 2 trap statements like this:

Code:
trap 'echo "got a signal!"' USR1
trap 'echo ""' 0


Last edited by dude2cool; 11-30-2011 at 09:30 AM..
# 3  
Old 11-30-2011
@dude2coo, thanks for the quick response.

After adding "0", nothing changed. Script still waits for user input after receiving USR1.
Thanks
# 4  
Old 11-30-2011
Thanks for testing. It is looking more and more like some bad behaviour from ksh93, something on the lines of the below url:

https://www-304.ibm.com/support/docv...id=isg1IY75886

Also can you runscript with set -x and paste output here.

And when you hit enter, does it manage to exit? If so we can simply pass a newline with that exit.

Last edited by dude2cool; 11-30-2011 at 09:55 AM..
# 5  
Old 11-30-2011
I took a look at ksh93 defect pointed by you... it might be this same, but I'm not sure - I think some research in source of ksh93 would be needed.

Let me paste the script again, now a bit modified.
Code:
[Linux]> cat a.ksh
#!/bin/ksh
typeset TEXT=""

trap 'echo "got a signal!"' USR1
trap 'echo ""' 0

# send USR1 signal after 5 seconds
( sleep 5; kill -USR1 ${$} ) &

echo "put some text here.... my pid is $$"
date
read TEXT
date
echo "I'm done $TEXT"

exit 0
[Linux]>

Now, run it with ksh -x

Code:
[Linux]> ksh -x a.ksh
+ TEXT=''
+ typeset TEXT
+ trap 'echo "got a signal!"' USR1
+ trap 'echo ""' 0
+ echo 'put some text here.... my pid is 17403'
put some text here.... my pid is 17403
+ date
+ sleep 5
Wed Nov 30 15:54:50 EST 2011
+ read TEXT
+ kill -USR1 17403
+ echo 'got a signal!'
got a signal!
waiting for a while and pressing enter...
+ date
Wed Nov 30 15:55:20 EST 2011
+ echo $'I\'m done waiting for a while and pressing enter...'
I'm done waiting for a while and pressing enter...
+ exit 0
+ echo ''

[Linux]>

Signal comes and it is handled as it should. However interpreter still sits on read instead of continuing with next instruction.

But, try again and replace "read TEXT" with "sleep 20" and it works as I expect it to be working:

Code:
[Linux]> cat a.ksh
#!/bin/ksh
typeset TEXT=""

trap 'echo "got a signal!"' USR1
trap 'echo ""' 0

# send USR1 signal after 5 seconds
( sleep 5; kill -USR1 ${$} ) &

echo "put some text here.... my pid is $$"
date
sleep 20
date
echo "I'm done $TEXT"

exit 0


# Now run it

[Linux]> ksh -x ./a.ksh
+ TEXT=''
+ typeset TEXT
+ trap 'echo "got a signal!"' USR1
+ trap 'echo ""' 0
+ echo 'put some text here.... my pid is 16012'
put some text here.... my pid is 16012
+ date
+ sleep 5
Wed Nov 30 15:51:26 EST 2011
+ sleep 20
+ kill -USR1 16012
+ echo 'got a signal!'
got a signal!
+ date
Wed Nov 30 15:51:31 EST 2011
+ echo $'I\'m done '
I'm done
+ exit 0
+ echo ''

[Linux]>

Thanks
bzk
# 6  
Old 11-30-2011
It may be an operating system incompatibility. POSIX allows a signal to interrupt a read() command, but I don't think it requires it.

Tooling up to see if I can reproduce this behavior in raw C.

---------- Post updated at 03:32 PM ---------- Previous update was at 03:14 PM ----------

Thought I'd looked at that before, and had. This program:

Code:
#include <stdio.h>
#include <signal.h>
#include <unistd.h>

int handler(int sig)
{
        fprintf(stderr, "!!!\n");
}

int main(void)
{
        char buf[512];
        ssize_t s;
        signal(SIGALRM, handler);
        alarm(1);
        s=read(STDIN_FILENO, buf, 512);
        if(s <= 0) perror("Error");
        return(0);
}

Code:
$ ./a.out
!!!
^C
$

So receiving SIGALRM doesn't necessarily cause read() to return EINTR.

Looking around the man pages, I find this in man 7 signal:

Code:
   Interruption of System Calls and Library Functions by Signal Handlers
       If  a signal handler is invoked while a system call or library function
       call is blocked, then either:

       * the call is automatically restarted after the signal handler returns;
         or

       * the call fails with the error EINTR.

       Which  of  these  two  behaviors  occurs  depends  on the interface and
       whether or not the signal handler was established using the  SA_RESTART
       flag  (see sigaction(2)).  The details vary across Unix systems; below,
       the details for Linux.

       If a blocked call to one of the following interfaces is interrupted  by
       a  signal  handler, then the call will be automatically restarted after
       the signal handler returns if the SA_RESTART flag was  used;  otherwise
       the call will fail with the error EINTR:

           * read(2),  readv(2),  write(2),  writev(2),  and ioctl(2) calls on
             "slow" devices.  A "slow" device is one where the  I/O  call  may
             block  for  an indefinite time, for example, a terminal, pipe, or
             socket.  (A disk is not a slow device according to  this  defini-
             tion.)   If  an I/O call on a slow device has already transferred
             some data by the time it is interrupted by a signal handler, then
             the  call  will  return a success status (normally, the number of
             bytes transferred).

...

Let's try that out:

Code:
#include <stdio.h>
#include <signal.h>
#include <unistd.h>

int handler(int sig)
{
        fprintf(stderr, "!!!\n");
}

int main(void)
{
        struct sigaction act, old;
        char buf[512];
        ssize_t s;

        act.sa_handler=handler;
        sigemptyset(&act.sa_mask);
        act.sa_flags=SA_RESETHAND;
        sigaction(SIGALRM, &act, &old);

        alarm(1);
        s=read(STDIN_FILENO, buf, 512);
        if(s <= 0) perror("Error");
        return(0);
}

Code:
$ ./a.out
!!!
Error: Interrupted system call

$

So Linux signals can cause EINTR, but it's an optional feature.

If KSH is really, really supposed to get EINTR when signalled, that it doesn't is a bug in KSH since Linux can do that if you use sigaction instead of signal(). (You can also turn it off in sigaction with SA_RESTART). I'm not convinced it's supposed to be a portable feature in any case though.
This User Gave Thanks to Corona688 For This Post:
# 7  
Old 11-30-2011
Quote:
Originally Posted by bzk
I took a look at ksh93 defect pointed by you... it might be this same, but I'm not sure - I think some research in source of ksh93 would be needed.

Let me paste the script again, now a bit modified.
[code]
....
bzk
in linux when read (bash builtin) executes,(read() starts to waiting for reading data on the fd,or receive a signal eg.usr2 or defined others),process is blocked with `rt_sigprocmask(SIG_BLOCK, [USR1], [USR1],...)` so USR1 signal is blocked.Before this changed to default action with `rt_sigaction(SIGUSR1..`) by bash and also ksh(only linux not sunos)

in linux when read(ksh/ksh93 builtin) executes,(select() starts to waiting for input..)
select returns ERESTARTNOHAND for restart to listening/waiting its own fd(s) after receive the usr1 signal.so it is basically ignored.select will continue reads.

in solaris bash exhibits the same behavior like linux.so firsty, read() returns error with EINTR(call was interrupted by a signal (this is usr1 and prints "Received signal #16, SIGUSR1, in read() [caught]"),, but it resumes from memory with setcontext()..so read() will be continue..

but in solaris ksh,when you send the sigusr1/sigusr2 to any process (without internal signal handlers for this or even if it can be kill/terminate process as in default action), process terminated with this messg to screen "Received signal #16/#17, SIGUSR1, in read()..", as can be seen here,in solaris even if process on the read() syscall can be terminated without blocking signals..

regards
ygemici
This User Gave Thanks to ygemici For This Post:
Login or Register to Ask a Question

Previous Thread | Next Thread

10 More Discussions You Might Find Interesting

1. Shell Programming and Scripting

Signal trapped during read resumes sleeping

Greetings. This is my first post in this forum; I hope y'all find it useful. One caveat: "Concise" is my middle name. NOT! :D I am almost done with a shell script that runs as a daemon. It monitors a message log that is frequently written to by a database server but it it works my client will... (2 Replies)
Discussion started by: jakesalomon
2 Replies

2. Shell Programming and Scripting

ksh while read issue

Hello, I have used a chunk of ksh script similar to this in many places without any issue: while : do print; read OPTION?"Enter a number (q to quit): " expr ${OPTION} + 1 >/dev/null 2>&1 CHECKVAL=$? if }" != ${OPTION} ]; then ... (2 Replies)
Discussion started by: port43
2 Replies

3. UNIX for Advanced & Expert Users

Is there any shell command to show which interrupt handler handle which interrupt number?

Hi, all: Is there any shell command to show which interrupt handler handle which interrupt number in the system? li,kunlun (5 Replies)
Discussion started by: liklstar
5 Replies

4. UNIX for Advanced & Expert Users

Interrupt storm detected on "irq 20" throttling interrupt source

I receive the following warning messages on a very new machine which has FreeBSD 8.1 x64 installed on it: Interrupt storm detected on "irq 20" throttling interrupt source It is unclear what this means and what its origins are (motherboard? CPU? RAM?). I can start the desktop and the message is... (4 Replies)
Discussion started by: figaro
4 Replies

5. UNIX for Dummies Questions & Answers

simple way to read an array in ksh

hi, I'm a newbie to shell scripting. I wanted to initialise an array using basic for loop and read it. Then i want to print it as a .CSV file.. Any help would me much appreciated.. (1 Reply)
Discussion started by: pravsripad
1 Replies

6. Programming

how to discard instruction from previous signal

hello everyone, I'm having a problem doing signal handling so I post this thread to see if I could get help. I want asynchronous signal handling, that means when I'm processing a signal (signal 1), if the same signal comes (signal 2) that signal (signal 2) shall be processed; and moreover,... (7 Replies)
Discussion started by: nvhoang
7 Replies

7. Shell Programming and Scripting

read from console in ksh

I am stuck with a problem while reading data from a file.. while do read line #do some operations and if some condition is satisfied, ask the user to enter his choice. # using the choice continue operations. done < fileBeingRead.txt The... (4 Replies)
Discussion started by: ajaykumarns
4 Replies

8. Shell Programming and Scripting

is there any way to read a line twice in KSH

Hi All, Is there any way to read the previous line in file reading ? or is there any way to read a line twice in KSH ? thanks in advance !! Srini (6 Replies)
Discussion started by: Srini75
6 Replies

9. Shell Programming and Scripting

ksh read timeout

any idea on how to timeout the read statement for ksh? for bash u can use read -t option -t timeout Cause read to time out and return failure if a complete line of input is not read within timeout seconds. This option has ... (2 Replies)
Discussion started by: ashterix
2 Replies

10. UNIX for Advanced & Expert Users

Interrupt signal Control C takes too long to terminate a process

I have a process to terminate, and when keying Control C/ kill -int , it takes 15 minutes to half an hour to terminate the process. I've tried using kill -2, or keying control c twice, however the process seem to be killed abruptly, without writing into the log file. So the only way in order to... (8 Replies)
Discussion started by: paqui
8 Replies
Login or Register to Ask a Question