1 /* Multithread-safety test for setlocale_null_r (LC_ALL, ...).
2 Copyright (C) 2019-2020 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. */
21 #if USE_ISOC_THREADS || USE_POSIX_THREADS || USE_ISOC_AND_POSIX_THREADS || USE_WINDOWS_THREADS
31 #include "glthread/thread.h"
33 /* We want to use the system's setlocale() function here, not the gnulib
38 /* Some common locale names. */
40 #if defined _WIN32 && !defined __CYGWIN__
41 # define ENGLISH "English_United States"
42 # define GERMAN "German_Germany"
43 # define FRENCH "French_France"
44 # define ENCODING ".1252"
46 # define ENGLISH "en_US"
47 # define GERMAN "de_DE"
48 # define FRENCH "fr_FR"
50 # define ENCODING ".ISO8859-15"
52 # define ENCODING ".utf8"
54 # define ENCODING ".UTF-8"
58 static const char LOCALE1
[] = ENGLISH ENCODING
;
59 static const char LOCALE2
[] = GERMAN ENCODING
;
60 static const char LOCALE3
[] = FRENCH ENCODING
;
62 static char *expected
;
65 thread1_func (void *arg
)
69 char buf
[SETLOCALE_NULL_ALL_MAX
];
71 if (setlocale_null_r (LC_ALL
, buf
, sizeof (buf
)))
73 if (strcmp (expected
, buf
) != 0)
75 fprintf (stderr
, "thread1 disturbed by thread2!\n"); fflush (stderr
);
85 thread2_func (void *arg
)
89 char buf
[SETLOCALE_NULL_ALL_MAX
];
91 setlocale_null_r (LC_NUMERIC
, buf
, sizeof (buf
));
92 setlocale_null_r (LC_ALL
, buf
, sizeof (buf
));
100 main (int argc
, char *argv
[])
102 if (setlocale (LC_ALL
, LOCALE1
) == NULL
)
104 fprintf (stderr
, "Skipping test: LOCALE1 not recognized\n");
107 if (setlocale (LC_NUMERIC
, LOCALE2
) == NULL
)
109 fprintf (stderr
, "Skipping test: LOCALE2 not recognized\n");
112 if (setlocale (LC_TIME
, LOCALE3
) == NULL
)
114 fprintf (stderr
, "Skipping test: LOCALE3 not recognized\n");
118 expected
= strdup (setlocale (LC_ALL
, NULL
));
120 /* Create the two threads. */
121 gl_thread_create (thread1_func
, NULL
);
122 gl_thread_create (thread2_func
, NULL
);
124 /* Let them run for 5 seconds. */
126 struct timespec duration
;
128 duration
.tv_nsec
= 0;
130 nanosleep (&duration
, NULL
);
138 /* No multithreading available. */
145 fputs ("Skipping test: multithreading not enabled\n", stderr
);
151 /* Without locking, the results of this test would be:
153 musl libc crash < 10 sec
155 FreeBSD crash < 1 sec
157 OpenBSD crash < 1 sec
164 Solaris OpenIndiana OK
168 MSVC OK (assuming compiler option /MD !)