diff options
| -rw-r--r-- | src/stdio/fclose.c | 7 | ||||
| -rw-r--r-- | src/stdio/feof.c | 5 | ||||
| -rw-r--r-- | src/stdio/ferror.c | 5 | ||||
| -rw-r--r-- | src/stdio/fileno.c | 5 | ||||
| -rw-r--r-- | src/stdio/freopen.c | 24 | ||||
| -rw-r--r-- | src/stdio/fwide.c | 6 | 
6 files changed, 36 insertions, 16 deletions
diff --git a/src/stdio/fclose.c b/src/stdio/fclose.c index 8fdc3f7d..92bf7ff8 100644 --- a/src/stdio/fclose.c +++ b/src/stdio/fclose.c @@ -3,9 +3,12 @@  int fclose(FILE *f)  {  	int r; -	int perm = f->flags & F_PERM; +	int perm; +	 +	/* This lock is not paired with any unlock. */ +	FLOCK(f); -	if (!perm) { +	if (!(perm = f->flags & F_PERM)) {  		OFLLOCK();  		if (f->prev) f->prev->next = f->next;  		if (f->next) f->next->prev = f->prev; diff --git a/src/stdio/feof.c b/src/stdio/feof.c index 5d7f4b02..56da6b91 100644 --- a/src/stdio/feof.c +++ b/src/stdio/feof.c @@ -4,7 +4,10 @@  int feof(FILE *f)  { -	return !!(f->flags & F_EOF); +	FLOCK(f); +	int ret = !!(f->flags & F_EOF); +	FUNLOCK(f); +	return ret;  }  weak_alias(feof, feof_unlocked); diff --git a/src/stdio/ferror.c b/src/stdio/ferror.c index 8288a93d..d692eed9 100644 --- a/src/stdio/ferror.c +++ b/src/stdio/ferror.c @@ -4,7 +4,10 @@  int ferror(FILE *f)  { -	return !!(f->flags & F_ERR); +	FLOCK(f); +	int ret = !!(f->flags & F_ERR); +	FUNLOCK(f); +	return ret;  }  weak_alias(ferror, ferror_unlocked); diff --git a/src/stdio/fileno.c b/src/stdio/fileno.c index 9ffb26d5..ba7f9391 100644 --- a/src/stdio/fileno.c +++ b/src/stdio/fileno.c @@ -2,6 +2,11 @@  int fileno(FILE *f)  { +	/* f->fd never changes, but the lock must be obtained and released +	 * anyway since this function cannot return while another thread +	 * holds the lock. */ +	FLOCK(f); +	FUNLOCK(f);  	return f->fd;  } diff --git a/src/stdio/freopen.c b/src/stdio/freopen.c index c80ce3b4..7ae116d8 100644 --- a/src/stdio/freopen.c +++ b/src/stdio/freopen.c @@ -4,8 +4,9 @@   * hack the necessary parts of the new FILE into the old one, then   * close the new FILE. */ -/* Locking is not necessary because, in the event of failure, the stream - * passed to freopen is invalid as soon as freopen is called. */ +/* Locking IS necessary because another thread may provably hold the + * lock, via flockfile or otherwise, when freopen is called, and in that + * case, freopen cannot act until the lock is released. */  int __dup3(int, int, int); @@ -14,6 +15,8 @@ FILE *freopen(const char *restrict filename, const char *restrict mode, FILE *re  	int fl = __fmodeflags(mode);  	FILE *f2; +	FLOCK(f); +  	fflush(f);  	if (!filename) { @@ -22,21 +25,22 @@ FILE *freopen(const char *restrict filename, const char *restrict mode, FILE *re  		fl &= ~(O_CREAT|O_EXCL|O_CLOEXEC);  		if (syscall(SYS_fcntl, f->fd, F_SETFL, fl) < 0)  			goto fail; -		return f;  	} else {  		f2 = fopen(filename, mode);  		if (!f2) goto fail;  		if (f2->fd == f->fd) f2->fd = -1; /* avoid closing in fclose */  		else if (__dup3(f2->fd, f->fd, fl&O_CLOEXEC)<0) goto fail2; -	} -	f->flags = (f->flags & F_PERM) | f2->flags; -	f->read = f2->read; -	f->write = f2->write; -	f->seek = f2->seek; -	f->close = f2->close; +		f->flags = (f->flags & F_PERM) | f2->flags; +		f->read = f2->read; +		f->write = f2->write; +		f->seek = f2->seek; +		f->close = f2->close; -	fclose(f2); +		fclose(f2); +	} + +	FUNLOCK(f);  	return f;  fail2: diff --git a/src/stdio/fwide.c b/src/stdio/fwide.c index f4da47f6..48480685 100644 --- a/src/stdio/fwide.c +++ b/src/stdio/fwide.c @@ -5,6 +5,8 @@  int fwide(FILE *f, int mode)  { -	if (!f->mode) f->mode = NORMALIZE(mode); -	return f->mode; +	FLOCK(f); +	if (!f->mode) mode = f->mode = NORMALIZE(mode); +	FUNLOCK(f); +	return mode;  }  | 
