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