Incorect signal handling ?
Hi,
there is litlle programm:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <signal.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
static void empty(int sig)
{
printf ("hello\n");
return;
}void main()
{
int fd, a;
char buf[512];
if (fd = open("/tmp/nic", O_RDONLY) < 0)
{
perror ("open");
exit(1);
}
signal (SIGALRM, empty);
alarm (1);
a = read(fd, buf, 511);
while (a && a != -1) a = read(fd, buf, 511);
if (a == -1)
{
perror ("read");
exit(1);
}
else printf ("EOF\n");
exit(0);
}I open /tmp/nic and run compiled program.
There should be error EINTR in read, but isn't.
Why ?
Signature · 3 lines
Daniel Podlejski <[email protected]> ... Here await the birth of the son The seventh, the heavenly, the chosen one ...
Quoted 46 lines · Daniel Podlejski
Hi,
there is litlle programm:
#include <
stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <signal.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>static void empty(int sig)
{ printf ("hello\n"); return; }void
main(){ int fd, a; char buf[512]; if (fd = open("/tmp/nic", O_RDONLY) < 0) { perror ("open"); exit(1); } signal (SIGALRM, empty); alarm (1); a = read(fd, buf, 511); while (a && a != -1) a = read(fd, buf, 511); if (a == -1) { perror ("read"); exit(1); } else printf ("EOF\n"); exit(0); }
Quoted 4 lines
I open
/tmp/nicand run compiled program.
There should be error EINTR in read, but isn't.
Why ?
The test program contains several errors. Here is a 'fixed' version.
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <signal.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
static void empty(int sig)
{
printf ("hello\n");
return;
}void main()
{
int fd, a;
struct sigaction sa;
char buf[512];
if (fd = open("/dev/zero", O_RDONLY) < 0)
{
perror ("open");
exit(1);
}
sigaction(SIGALRM, NULL, &sa);
sa.sa_handler = empty;
sa.sa_flags = SA_INTERRUPT;
sigaction(SIGALRM, &sa, NULL);
alarm (1);
while ((a = read(fd, buf, 511)) > 0)
;
if (a == -1)
{
perror ("read");
exit(1);
}
else printf ("EOF\n");
exit(0);
}First, you need to read something that can be interrupted. A 511 byte read from a small file will probably never be interrupted. The code can be spending much more time in the 'while (funny stuff)' loop than it takes to read that file.
I chose to read from an infinite-size 'file'.
Second, your 'C' runtime library probably defaults to non-BSD signals. That is to say, the "SA_RESTART" bit is probably set in the flags. To get the system call interrupted, you need to have that bit clear. The way to do it is with sigaction(); signal() is just not capable of doing what you want, now that 'C' runtime libraries default to POSIX-signal behavior rather than BSD-signals.
FYI, main() can never be void. It must return an 'int'.
while (a && a != -1) a = read(fd, buf, 511);
doesn't make much sense. (a && a) is either TRUE or FALSE. It will, therefore NEVER be -1. Maybe you meant (a & a)? If so, why not just (a != -1) or (a > 0) ?
Cheers,
Dick Johnson
Penguin : Linux version 2.4.1 on an i686 machine (799.53 BogoMips).
"Memory is like gasoline. You use it up when you are running. Of course you get it all back when you reboot..."; Actual explanation obtained from the Micro$oft help desk.
Quoted 11 lines · Daniel Podlejski
Hi,
there is litlle programm:
signal (SIGALRM, empty); alarm (1); a = read(fd, buf, 511); while (a && a != -1) a = read(fd, buf, 511);
Quoted 2 lines
I open
/tmp/nicand run compiled program.
There should be error EINTR in read, but isn't.
"Fast" system calls (eg reads from disk) are generally uninterruptible; thus the signal will be deferred until the read() returns.
-Doug