diff options
Diffstat (limited to 'lib/libc/stdio/fclose.c')
-rw-r--r-- | lib/libc/stdio/fclose.c | 14 |
1 files changed, 14 insertions, 0 deletions
diff --git a/lib/libc/stdio/fclose.c b/lib/libc/stdio/fclose.c index f0629e8..3957b6a 100644 --- a/lib/libc/stdio/fclose.c +++ b/lib/libc/stdio/fclose.c @@ -41,6 +41,7 @@ __FBSDID("$FreeBSD$"); #include <stdio.h> #include <stdlib.h> #include "un-namespace.h" +#include <spinlock.h> #include "libc_private.h" #include "local.h" @@ -65,7 +66,20 @@ fclose(FILE *fp) FREELB(fp); fp->_file = -1; fp->_r = fp->_w = 0; /* Mess up if reaccessed. */ + + /* + * Lock the spinlock used to protect __sglue list walk in + * __sfp(). The __sfp() uses fp->_flags == 0 test as an + * indication of the unused FILE. + * + * Taking the lock prevents possible compiler or processor + * reordering of the writes performed before the final _flags + * cleanup, making sure that we are done with the FILE before + * it is considered available. + */ + STDIO_THREAD_LOCK(); fp->_flags = 0; /* Release this FILE for reuse. */ + STDIO_THREAD_UNLOCK(); FUNLOCKFILE(fp); return (r); } |