diff options
Diffstat (limited to 'gnulib-tests/test-setlocale_null-mt-all.c')
-rw-r--r-- | gnulib-tests/test-setlocale_null-mt-all.c | 169 |
1 files changed, 169 insertions, 0 deletions
diff --git a/gnulib-tests/test-setlocale_null-mt-all.c b/gnulib-tests/test-setlocale_null-mt-all.c new file mode 100644 index 0000000..19bdb55 --- /dev/null +++ b/gnulib-tests/test-setlocale_null-mt-all.c @@ -0,0 +1,169 @@ +/* Multithread-safety test for setlocale_null_r (LC_ALL, ...). + Copyright (C) 2019-2020 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* Written by Bruno Haible <bruno@clisp.org>, 2019. */ + +#include <config.h> + +#if USE_ISOC_THREADS || USE_POSIX_THREADS || USE_ISOC_AND_POSIX_THREADS || USE_WINDOWS_THREADS + +/* Specification. */ +#include <locale.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> + +#include "glthread/thread.h" + +/* We want to use the system's setlocale() function here, not the gnulib + override. */ +#undef setlocale + + +/* Some common locale names. */ + +#if defined _WIN32 && !defined __CYGWIN__ +# define ENGLISH "English_United States" +# define GERMAN "German_Germany" +# define FRENCH "French_France" +# define ENCODING ".1252" +#else +# define ENGLISH "en_US" +# define GERMAN "de_DE" +# define FRENCH "fr_FR" +# if defined __sgi +# define ENCODING ".ISO8859-15" +# elif defined __hpux +# define ENCODING ".utf8" +# else +# define ENCODING ".UTF-8" +# endif +#endif + +static const char LOCALE1[] = ENGLISH ENCODING; +static const char LOCALE2[] = GERMAN ENCODING; +static const char LOCALE3[] = FRENCH ENCODING; + +static char *expected; + +static void * +thread1_func (void *arg) +{ + for (;;) + { + char buf[SETLOCALE_NULL_ALL_MAX]; + + if (setlocale_null_r (LC_ALL, buf, sizeof (buf))) + abort (); + if (strcmp (expected, buf) != 0) + { + fprintf (stderr, "thread1 disturbed by thread2!\n"); fflush (stderr); + abort (); + } + } + + /*NOTREACHED*/ + return NULL; +} + +static void * +thread2_func (void *arg) +{ + for (;;) + { + char buf[SETLOCALE_NULL_ALL_MAX]; + + setlocale_null_r (LC_NUMERIC, buf, sizeof (buf)); + setlocale_null_r (LC_ALL, buf, sizeof (buf)); + } + + /*NOTREACHED*/ + return NULL; +} + +int +main (int argc, char *argv[]) +{ + if (setlocale (LC_ALL, LOCALE1) == NULL) + { + fprintf (stderr, "Skipping test: LOCALE1 not recognized\n"); + return 77; + } + if (setlocale (LC_NUMERIC, LOCALE2) == NULL) + { + fprintf (stderr, "Skipping test: LOCALE2 not recognized\n"); + return 77; + } + if (setlocale (LC_TIME, LOCALE3) == NULL) + { + fprintf (stderr, "Skipping test: LOCALE3 not recognized\n"); + return 77; + } + + expected = strdup (setlocale (LC_ALL, NULL)); + + /* Create the two threads. */ + gl_thread_create (thread1_func, NULL); + gl_thread_create (thread2_func, NULL); + + /* Let them run for 5 seconds. */ + { + struct timespec duration; + duration.tv_sec = 5; + duration.tv_nsec = 0; + + nanosleep (&duration, NULL); + } + + return 0; +} + +#else + +/* No multithreading available. */ + +#include <stdio.h> + +int +main () +{ + fputs ("Skipping test: multithreading not enabled\n", stderr); + return 77; +} + +#endif + +/* Without locking, the results of this test would be: +glibc OK +musl libc crash < 10 sec +macOS crash < 1 sec +FreeBSD crash < 1 sec +NetBSD crash < 2 sec +OpenBSD crash < 1 sec +AIX crash < 2 sec +HP-UX OK +IRIX OK +Solaris 10 OK +Solaris 11.0 OK +Solaris 11.4 OK +Solaris OpenIndiana OK +Haiku crash < 1 sec +Cygwin crash < 1 sec +mingw OK +MSVC OK (assuming compiler option /MD !) +*/ |