Skip to contentSkip to conversation

Can EINTR be handled the way BSD handles it? -- a plea from a user-land programmer...

DISCUSSION George Talbot 5 participants 7 messages Nov 6, 2000 – Nov 7, 2000 1 message not in the archive

lore
Share & tools
lore

A message that is not in the archive (sent off-list or not yet received): [email protected]

#1 lore raw

I respectfully disagree that programs which don't surround some of the most common system calls with

	do
	{
		rv = __some_system_call__(...);
	} while (rv == -1 && errno == EINTR);

are broken. Especially if those programs don't use signals. The problem that I'm raising is that the default behavior of returning EINTR from system calls is, in my opinion, an application reliabilty problem. The specific problem I'm having is that glibc uses signals to implement multiple threads, and because of the EINTR behavior, expose multithreaded programs to this behavior that weren't necessarily written to use signals.

It's a useability and portability issue, especially considering that I might be using pthreads so that I can avoid signal handling entirely. I might want to do this because I want to be portable to non-UNIX systems that implement the pthreads API.

I _was_not_ too lazy to read the documentation, though I don't have a copy of POSIX.

Does POSIX require that pthreads programs be signal-aware in the EINTR sense? Could this be considered a bug?

--
George T. Talbot
<[email protected]>

Quoted 16 lines · Marc Lehmann
Quoted 2 lines · On Fri, Nov 03, 2000 at 02:49:37PM -0500, [email protected] wrote:

After reading about SA_RESTART, ok. However, couldn't those applications that require it enable this behaviour explicitly?

No, broken applications that require specific bsd behaviour should just be compiled with -D_BSD_SOURCE. If you need newer features then be prepared to fix the program.

Quoted 3 lines

The problem I'm having right now is with pthread_create() failing because deep somewhere in either the kernel or glibc, nanosleep() returns EINTR during said pthread_create() and pthread_create() fails.

This has hardly something to do with the signal reliability issue, unless you compiled your own threads library. You might want to file a bug report for libpthread otherwise.

Quoted 8 lines
Quoted 3 lines

I don't mean to sound like a psycho on this, but I can't see why SA_RESTART isn't the default behavior. Maybe I'm missing something somewhere.

Yes, you are missing signal(2) or the glibc info file, so the real question is: why were you too lazy to read the documentation???

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
Please read the FAQ at http://www.tux.org/lkml/

#2 lore raw

Date: Mon, 6 Nov 2000 09:13:25 -0500 (EST)
From: George Talbot <[email protected]>

I respectfully disagree that programs which don't surround some of the most common system calls with

	   do
	   {
		   rv = __some_system_call__(...);
	   } while (rv == -1 && errno == EINTR);

are broken. Especially if those programs don't use signals. The problem that I'm raising is that the default behavior of returning EINTR from system calls is, in my opinion, an application reliabilty problem. The specific problem I'm having is that glibc uses signals to implement multiple threads, and because of the EINTR behavior, expose multithreaded programs to this behavior that weren't necessarily written to use signals.

Arguably though the bug is in glibc, in that if it's using signals behinds the scenes, it should have passed SA_RESTART to sigaction.

However, from a portability point of view, you should *always* surround certain system calls with while loops, since even if your program doesn't use signals, if you run that program on a System-V derived Unix system, and someone types ^Z at the wrong moment, you can also get an
EINTR. Similarly, you should always check the return value from write
and make sure all of what you asked to be written, was actually written.

What I normally do is have a full_write routine which looks something like this:

static errcode_t full_write(int fd, void *buf, int count)

{
	char	*cp = buf;
	int	left = count, c;

	while (left) {
		c = write(fd, cp, left);
		if (c < 0) {
			if (errno == EINTR || errno == EAGAIN)
				continue;
			return errno;
		}
		left -= c;
		cp += c;
	}
	return 0;
}

It's like checking the return value from malloc(). Not everyone does it, but even if it's not needed 99% of the time, it's a darned good idea to do that.

- Ted
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
Please read the FAQ at http://www.tux.org/lkml/

#3 lore raw
Quoted 2 lines · Theodore Y. Ts'o

Arguably though the bug is in glibc, in that if it's using signals behinds the scenes, it should have passed SA_RESTART to sigaction.

Why are you talking such a nonsense?

Quoted 41 lines

However, from a portability point of view, you should *always* surround certain system calls with while loops, since even if your program doesn't use signals, if you run that program on a System-V derived Unix system, and someone types ^Z at the wrong moment, you can also get an
EINTR. Similarly, you should always check the return value from write
and make sure all of what you asked to be written, was actually written.

What I normally do is have a full_write routine which looks something like this:

static errcode_t full_write(int fd, void *buf, int count)

{
	char	*cp = buf;
	int	left = count, c;

	while (left) {
		c = write(fd, cp, left);
		if (c < 0) {
			if (errno == EINTR || errno == EAGAIN)
				continue;
			return errno;
		}
		left -= c;
		cp += c;
	}
	return 0;
}

It's like checking the return value from malloc(). Not everyone does it, but even if it's not needed 99% of the time, it's a darned good idea to do that.

- Ted
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
Please read the FAQ at http://www.tux.org/lkml/

Signature · 7 lines
---------------.                          ,-.   1325 Chesapeake Terrace
Ulrich Drepper  \    ,-------------------'   \  Sunnyvale, CA 94089 USA
Red Hat          `--' drepper at redhat.com   `------------------------
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
Please read the FAQ at http://www.tux.org/lkml/
#4 lore raw

From: Ulrich Drepper <[email protected]>
Date: 06 Nov 2000 10:50:37 -0800

Quoted 2 lines

Arguably though the bug is in glibc, in that if it's using signals behinds the scenes, it should have passed SA_RESTART to sigaction.

Why are you talking such a nonsense?

The claim was made that pthreads was using signals behind the scenes, so that programs which weren't expecting that system calls to get interrupted were getting interrupted. Hence, one could make the argument that if the pthreads code had used SA_RESTART to set up its signal handlers, then this situation wouldn't have come up.

I haven't looked more deeply into this. As far as I'm concerned, threads === "more rope" and use of threads should be avoided whenever possible, even if Linux had a decent threads implementation....

- Ted
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
Please read the FAQ at http://www.tux.org/lkml/

#5 lore raw
In reply to Theodore Y. Ts'o
Quoted 6 lines · Ulrich Drepper
Quoted 2 lines · Theodore Y. Ts'o

Arguably though the bug is in glibc, in that if it's using signals behinds the scenes, it should have passed SA_RESTART to sigaction.

Why are you talking such a nonsense?

[Note to self: remove kitten from keyboard before writing mail.]

Glibc has to use signals because there *still* is not mechanism in the kernel to allow synchronization. After how many years.

I don't blame Linux. He has no interest in threads and therefore spends not much time thinking about it. But everybody who's complaining about things like this has to be willing to fix the real problems.

Get your ass up and write a fast semaphore/mutex system.

Signature · 7 lines
---------------.                          ,-.   1325 Chesapeake Terrace
Ulrich Drepper  \    ,-------------------'   \  Sunnyvale, CA 94089 USA
Red Hat          `--' drepper at redhat.com   `------------------------
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
Please read the FAQ at http://www.tux.org/lkml/
#6 lore raw

Hello!

Quoted 2 lines

Glibc has to use signals because there *still* is not mechanism in the kernel to allow synchronization.

Could you tell why does it use SA_INTERRUPT on its internal signals?

Alexey
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
Please read the FAQ at http://www.tux.org/lkml/

#7 lore raw
In reply to George Talbot
Quoted 7 lines · George Talbot

I respectfully disagree that programs which don't surround some of the most common system calls with

	do
	{
		rv = __some_system_call__(...);
	} while (rv == -1 && errno == EINTR);

welcome to Unix. this is how it is, and it's not just linux. and it's not just glibc/linuxthreads. in your code do you go about setting all signals to SA_RESTART? if not then you're subject to the vagaries of whatever the default signal settings are.

ted mentioned ^Z... there's also strace/truss/ktrace (depending on your flavour of unix). there's also page-out/in (and on some unixes there's swap-out/in).

it's something which bites lots of folks. gnu tar had this bug for at least 5 years, and may still have it -- i got tired of submitting the bug fix.

-dean

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
Please read the FAQ at http://www.tux.org/lkml/