about summary refs log tree commit diff
path: root/src/stdio/__stdio_read.c
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2012-02-02 00:11:29 -0500
committerRich Felker <dalias@aerifal.cx>2012-02-02 00:11:29 -0500
commit58165923890865a6ac042fafce13f440ee986fd9 (patch)
tree1a2e608393566ba3184e95f224cbd5a538e275a2 /src/stdio/__stdio_read.c
parent4948a24df21c1e80bedc1f302547c9cb26e4dbfe (diff)
downloadmusl-58165923890865a6ac042fafce13f440ee986fd9.tar.gz
musl-58165923890865a6ac042fafce13f440ee986fd9.tar.xz
musl-58165923890865a6ac042fafce13f440ee986fd9.zip
make stdio open, read, and write operations cancellation points
it should be noted that only the actual underlying buffer flush and
fill operations are cancellable, not reads from or writes to the
buffer. this behavior is compatible with POSIX, which makes all
cancellation points in stdio optional, and it achieves the goal of
allowing cancellation of a thread that's "stuck" on IO (due to a
non-responsive socket/pipe peer, slow/stuck hardware, etc.) without
imposing any measurable performance cost.
Diffstat (limited to 'src/stdio/__stdio_read.c')
-rw-r--r--src/stdio/__stdio_read.c11
1 files changed, 10 insertions, 1 deletions
diff --git a/src/stdio/__stdio_read.c b/src/stdio/__stdio_read.c
index 218bd88d..ee17a576 100644
--- a/src/stdio/__stdio_read.c
+++ b/src/stdio/__stdio_read.c
@@ -1,4 +1,11 @@
 #include "stdio_impl.h"
+#include <pthread.h>
+
+static void cleanup(void *p)
+{
+	FILE *f = p;
+	if (!f->lockcount) __unlockfile(f);
+}
 
 size_t __stdio_read(FILE *f, unsigned char *buf, size_t len)
 {
@@ -8,7 +15,9 @@ size_t __stdio_read(FILE *f, unsigned char *buf, size_t len)
 	};
 	ssize_t cnt;
 
-	cnt = syscall(SYS_readv, f->fd, iov, 2);
+	pthread_cleanup_push(cleanup, f);
+	cnt = syscall_cp(SYS_readv, f->fd, iov, 2);
+	pthread_cleanup_pop(0);
 	if (cnt <= 0) {
 		f->flags |= F_EOF ^ ((F_ERR^F_EOF) & cnt);
 		f->rpos = f->rend = 0;