summaryrefslogtreecommitdiff
path: root/src/regress/lib/libc/stdio_threading/flockfile/flockfile_test.c
diff options
context:
space:
mode:
authorguenther <>2026-01-19 23:01:00 +0000
committerguenther <>2026-01-19 23:01:00 +0000
commit28d8cf0bbfe2d8e27749a1453bd2771c8e41c31b (patch)
tree70a6f669625e0a3bd8d7ad550c55357341c846f0 /src/regress/lib/libc/stdio_threading/flockfile/flockfile_test.c
parent72cdd91797afb2b9796ee9f67324a53c5fc6effe (diff)
downloadopenbsd-28d8cf0bbfe2d8e27749a1453bd2771c8e41c31b.tar.gz
openbsd-28d8cf0bbfe2d8e27749a1453bd2771c8e41c31b.tar.bz2
openbsd-28d8cf0bbfe2d8e27749a1453bd2771c8e41c31b.zip
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@
Diffstat (limited to 'src/regress/lib/libc/stdio_threading/flockfile/flockfile_test.c')
-rwxr-xr-xsrc/regress/lib/libc/stdio_threading/flockfile/flockfile_test.c78
1 files changed, 78 insertions, 0 deletions
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 @@
1/* $OpenBSD: flockfile_test.c,v 1.1 2026/01/19 23:01:00 guenther Exp $ */
2/*
3 * Copyright (c) 2026 Philip Guenther <guenther@openbsd.org>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18#include <stdio.h>
19#include <pthread.h>
20#include "local.h"
21
22pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
23pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
24int did_test1 = 0;
25
26static void *
27test1(void *v)
28{
29 int r;
30
31 if (ftrylockfile(stdin) == 0)
32 errx(1, "Lock on stdin never held");
33
34 if ((r = pthread_mutex_lock(&lock)))
35 errc(1, r, "could not lock lock");
36 did_test1 = 1;
37 if ((r = pthread_cond_signal(&cond)))
38 errc(1, r, "could not signal cond");
39 if ((r = pthread_mutex_unlock(&lock)))
40 errc(1, r, "could not unlock lock");
41
42 flockfile(stdin);
43 funlockfile(stdin);
44 return NULL;
45}
46
47int
48main(void)
49{
50 int fd, r;
51 pthread_t thr;
52
53 /*
54 * Make sure flockfile() is handled correctly before the first
55 * thread is created.
56 */
57 flockfile(stdin);
58 flockfile(stdin);
59
60 if ((r = pthread_create(&thr, NULL, test1, NULL)))
61 warnc(r, "could not create thread");
62
63 if ((r = pthread_mutex_lock(&lock)))
64 errc(1, r, "could not lock lock");
65 while (did_test1 == 0)
66 if ((r = pthread_cond_wait(&cond, &lock)))
67 errc(1, r, "could not wait on cond");
68 if ((r = pthread_mutex_unlock(&lock)))
69 errc(1, r, "could not unlock lock");
70
71 funlockfile(stdin);
72 funlockfile(stdin);
73
74 if ((r = pthread_join(thr, NULL)))
75 warnc(r, "could not join thread");
76
77 exit(0);
78}