2001-04-12 20:32:05

by Daniel Podlejski

[permalink] [raw]
Subject: 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 ?

--
Daniel Podlejski <[email protected]>
... Here await the birth of the son
The seventh, the heavenly, the chosen one ...


2001-04-12 21:33:39

by Richard B. Johnson

[permalink] [raw]
Subject: Re: Incorect signal handling ?

On Thu, 12 Apr 2001, Daniel Podlejski wrote:

> 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 ?
>

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.


2001-04-12 21:58:21

by Doug McNaught

[permalink] [raw]
Subject: Re: Incorect signal handling ?

Daniel Podlejski <[email protected]> writes:

> Hi,
>
> there is litlle programm:
>
> signal (SIGALRM, empty);
> alarm (1);
>
> a = read(fd, buf, 511);
>
> while (a && a != -1) a = read(fd, buf, 511);

> I open /tmp/nic and 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