openat: don’t close (-1)
[gnulib.git] / tests / test-setlocale_null-mt-all.c
blob567a289fa9c345e171883ada083cc67f131ac59d
1 /* Multithread-safety test for setlocale_null_r (LC_ALL, ...).
2 Copyright (C) 2019-2024 Free Software Foundation, Inc.
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <https://www.gnu.org/licenses/>. */
17 /* Written by Bruno Haible <bruno@clisp.org>, 2019. */
19 #include <config.h>
21 /* Work around GCC bug 44511. */
22 #if _GL_GNUC_PREREQ (4, 3)
23 # pragma GCC diagnostic ignored "-Wreturn-type"
24 #endif
26 #if USE_ISOC_THREADS || USE_POSIX_THREADS || USE_ISOC_AND_POSIX_THREADS || USE_WINDOWS_THREADS
28 /* Specification. */
29 #include <locale.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <time.h>
36 #include "glthread/thread.h"
38 /* We want to use the system's setlocale() function here, not the gnulib
39 override. */
40 #undef setlocale
43 /* Some common locale names. */
45 #if defined _WIN32 && !defined __CYGWIN__
46 # define ENGLISH "English_United States"
47 # define GERMAN "German_Germany"
48 # define FRENCH "French_France"
49 # define ENCODING ".1252"
50 #else
51 # define ENGLISH "en_US"
52 # define GERMAN "de_DE"
53 # define FRENCH "fr_FR"
54 # if defined __sgi
55 # define ENCODING ".ISO8859-15"
56 # elif defined __hpux
57 # define ENCODING ".utf8"
58 # else
59 # define ENCODING ".UTF-8"
60 # endif
61 #endif
63 static const char LOCALE1[] = ENGLISH ENCODING;
64 static const char LOCALE2[] = GERMAN ENCODING;
65 static const char LOCALE3[] = FRENCH ENCODING;
67 static char *expected;
69 static void *
70 thread1_func (void *arg)
72 for (;;)
74 char buf[SETLOCALE_NULL_ALL_MAX];
76 if (setlocale_null_r (LC_ALL, buf, sizeof (buf)))
77 abort ();
78 if (strcmp (expected, buf) != 0)
80 fprintf (stderr, "thread1 disturbed by thread2!\n"); fflush (stderr);
81 abort ();
85 /*NOTREACHED*/
88 static void *
89 thread2_func (void *arg)
91 for (;;)
93 char buf[SETLOCALE_NULL_ALL_MAX];
95 setlocale_null_r (LC_NUMERIC, buf, sizeof (buf));
96 setlocale_null_r (LC_ALL, buf, sizeof (buf));
99 /*NOTREACHED*/
103 main (int argc, char *argv[])
105 if (setlocale (LC_ALL, LOCALE1) == NULL)
107 fprintf (stderr, "Skipping test: LOCALE1 not recognized\n");
108 return 77;
110 if (setlocale (LC_NUMERIC, LOCALE2) == NULL)
112 fprintf (stderr, "Skipping test: LOCALE2 not recognized\n");
113 return 77;
115 if (setlocale (LC_TIME, LOCALE3) == NULL)
117 fprintf (stderr, "Skipping test: LOCALE3 not recognized\n");
118 return 77;
121 expected = strdup (setlocale (LC_ALL, NULL));
123 /* Create the two threads. */
124 gl_thread_create (thread1_func, NULL);
125 gl_thread_create (thread2_func, NULL);
127 /* Let them run for 5 seconds. */
129 struct timespec duration;
130 duration.tv_sec = 5;
131 duration.tv_nsec = 0;
133 nanosleep (&duration, NULL);
136 return 0;
139 #else
141 /* No multithreading available. */
143 #include <stdio.h>
146 main ()
148 fputs ("Skipping test: multithreading not enabled\n", stderr);
149 return 77;
152 #endif
154 /* Without locking, the results of this test would be:
155 glibc OK
156 musl libc crash < 10 sec
157 macOS crash < 1 sec
158 FreeBSD crash < 1 sec
159 NetBSD crash < 2 sec
160 OpenBSD crash < 1 sec
161 AIX crash < 2 sec
162 HP-UX OK
163 IRIX OK
164 Solaris 10 OK
165 Solaris 11.0 OK
166 Solaris 11.4 OK
167 Solaris OpenIndiana OK
168 Haiku crash < 1 sec
169 Cygwin < 3.4.6 crash < 1 sec
170 mingw OK
171 MSVC OK (assuming compiler option /MD !)