Blame gl/tests/test-setlocale_null-mt-one.c

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
*/