From 28d8cf0bbfe2d8e27749a1453bd2771c8e41c31b Mon Sep 17 00:00:00 2001 From: guenther <> Date: Mon, 19 Jan 2026 23:01:00 +0000 Subject: While almost all the libc locks are taken and released in the same libc call, flockfile() and ftrylockfile() can be called when single-threaded and then--while 'holding' the lock--the process can create another thread, resulting in a broken state. Have the f{lock,trylock,unlock}file() APIs *always* do real locking so the exposed state is always consistent. ok dlg@ --- src/regress/lib/libc/stdio_threading/Makefile | 2 +- .../lib/libc/stdio_threading/flockfile/Makefile | 6 ++ .../stdio_threading/flockfile/flockfile_test.c | 78 ++++++++++++++++++++++ 3 files changed, 85 insertions(+), 1 deletion(-) create mode 100644 src/regress/lib/libc/stdio_threading/flockfile/Makefile create mode 100755 src/regress/lib/libc/stdio_threading/flockfile/flockfile_test.c (limited to 'src/regress/lib/libc') diff --git a/src/regress/lib/libc/stdio_threading/Makefile b/src/regress/lib/libc/stdio_threading/Makefile index e42481afc2..5823b6e284 100644 --- a/src/regress/lib/libc/stdio_threading/Makefile +++ b/src/regress/lib/libc/stdio_threading/Makefile @@ -1,3 +1,3 @@ -SUBDIR += fopen fread fwrite fgetln fgets fputs +SUBDIR += fopen fread fwrite fgetln fgets fputs flockfile .include diff --git a/src/regress/lib/libc/stdio_threading/flockfile/Makefile b/src/regress/lib/libc/stdio_threading/flockfile/Makefile new file mode 100644 index 0000000000..171ccc7ac7 --- /dev/null +++ b/src/regress/lib/libc/stdio_threading/flockfile/Makefile @@ -0,0 +1,6 @@ +TOPDIR=${.CURDIR} +PROG=flockfile_test +CFLAGS+=-I${TOPDIR}/../include/ +LDFLAGS+=-lpthread + +.include diff --git a/src/regress/lib/libc/stdio_threading/flockfile/flockfile_test.c b/src/regress/lib/libc/stdio_threading/flockfile/flockfile_test.c new file mode 100755 index 0000000000..034a753cd9 --- /dev/null +++ b/src/regress/lib/libc/stdio_threading/flockfile/flockfile_test.c @@ -0,0 +1,78 @@ +/* $OpenBSD: flockfile_test.c,v 1.1 2026/01/19 23:01:00 guenther Exp $ */ +/* + * Copyright (c) 2026 Philip Guenther + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include "local.h" + +pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; +pthread_cond_t cond = PTHREAD_COND_INITIALIZER; +int did_test1 = 0; + +static void * +test1(void *v) +{ + int r; + + if (ftrylockfile(stdin) == 0) + errx(1, "Lock on stdin never held"); + + if ((r = pthread_mutex_lock(&lock))) + errc(1, r, "could not lock lock"); + did_test1 = 1; + if ((r = pthread_cond_signal(&cond))) + errc(1, r, "could not signal cond"); + if ((r = pthread_mutex_unlock(&lock))) + errc(1, r, "could not unlock lock"); + + flockfile(stdin); + funlockfile(stdin); + return NULL; +} + +int +main(void) +{ + int fd, r; + pthread_t thr; + + /* + * Make sure flockfile() is handled correctly before the first + * thread is created. + */ + flockfile(stdin); + flockfile(stdin); + + if ((r = pthread_create(&thr, NULL, test1, NULL))) + warnc(r, "could not create thread"); + + if ((r = pthread_mutex_lock(&lock))) + errc(1, r, "could not lock lock"); + while (did_test1 == 0) + if ((r = pthread_cond_wait(&cond, &lock))) + errc(1, r, "could not wait on cond"); + if ((r = pthread_mutex_unlock(&lock))) + errc(1, r, "could not unlock lock"); + + funlockfile(stdin); + funlockfile(stdin); + + if ((r = pthread_join(thr, NULL))) + warnc(r, "could not join thread"); + + exit(0); +} -- cgit v1.2.3-55-g6feb