summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKurt Miller <kurt@cvs.openbsd.org>2006-12-01 16:34:42 +0000
committerKurt Miller <kurt@cvs.openbsd.org>2006-12-01 16:34:42 +0000
commitcc3275586fa747dea8554f15810e367f8f6a7056 (patch)
tree6a7e5eb36a55a37da6bb030c5e6c92ebc8a39f4a
parenta66448ed11b2f3fb46ae2bf1385cf042f09ac4ce (diff)
Normally pipes created by threaded apps are left non-blocking after being
closed so that a threaded child process can still read it without blocking. However, leaving stdin/out/err non-blocking when closed is bad because it can be shared with non-threaded apps that can't deal with a non-blocking file descriptor (i.e. cat). Therefore special case stdin/out/err pipes so that they are reset to blocking upon a close(). Tested by robert@, jolan@ and myself with multiple OOo builds on mp systems where the problem was seen more frequently.
-rw-r--r--lib/libpthread/uthread/uthread_fd.c11
1 files changed, 6 insertions, 5 deletions
diff --git a/lib/libpthread/uthread/uthread_fd.c b/lib/libpthread/uthread/uthread_fd.c
index c226cc801c2..6d840cb2005 100644
--- a/lib/libpthread/uthread/uthread_fd.c
+++ b/lib/libpthread/uthread/uthread_fd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uthread_fd.c,v 1.26 2006/09/26 15:09:59 kurt Exp $ */
+/* $OpenBSD: uthread_fd.c,v 1.27 2006/12/01 16:34:41 kurt Exp $ */
/*
* Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
* All rights reserved.
@@ -131,7 +131,8 @@ _thread_fs_flags_replace(int fd, struct fs_flags *new_status_flags)
* the parent and child will normally close the file
* descriptor of the end of the pipe that they are not
* using, which would then cause any reads to block
- * indefinitely.
+ * indefinitely. However, stdin/out/err will be reset
+ * to avoid leaving them as non-blocking indefinitely.
*
* Files that we cannot fstat are probably not regular
* so we don't bother with them.
@@ -140,9 +141,9 @@ _thread_fs_flags_replace(int fd, struct fs_flags *new_status_flags)
* the status flags with a shared version.
*/
if (new_status_flags == NULL &&
- (_thread_sys_fstat(fd, &sb) == 0) &&
- ((S_ISREG(sb.st_mode) || S_ISCHR(sb.st_mode)) &&
- (old_status_flags->flags & O_NONBLOCK) == 0))
+ (old_status_flags->flags & O_NONBLOCK) == 0 &&
+ (fd < 3 || (_thread_sys_fstat(fd, &sb) == 0 &&
+ (S_ISREG(sb.st_mode) || S_ISCHR(sb.st_mode)))))
{
/* Get the current flags: */
flags = _thread_sys_fcntl(fd, F_GETFL, NULL);