(root)/
m4-1.4.19/
tests/
test-setlocale_null-mt-all.c
       1  /* Multithread-safety test for setlocale_null_r (LC_ALL, ...).
       2     Copyright (C) 2019-2021 Free Software Foundation, Inc.
       3  
       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.
       8  
       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.
      13  
      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/>.  */
      16  
      17  /* Written by Bruno Haible <bruno@clisp.org>, 2019.  */
      18  
      19  #include <config.h>
      20  
      21  /* Work around GCC bug 44511.  */
      22  #if 4 < __GNUC__ + (3 <= __GNUC_MINOR__)
      23  # pragma GCC diagnostic ignored "-Wreturn-type"
      24  #endif
      25  
      26  #if USE_ISOC_THREADS || USE_POSIX_THREADS || USE_ISOC_AND_POSIX_THREADS || USE_WINDOWS_THREADS
      27  
      28  /* Specification.  */
      29  #include <locale.h>
      30  
      31  #include <stdio.h>
      32  #include <stdlib.h>
      33  #include <string.h>
      34  #include <time.h>
      35  
      36  #include "glthread/thread.h"
      37  
      38  /* We want to use the system's setlocale() function here, not the gnulib
      39     override.  */
      40  #undef setlocale
      41  
      42  
      43  /* Some common locale names.  */
      44  
      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
      62  
      63  static const char LOCALE1[] = ENGLISH ENCODING;
      64  static const char LOCALE2[] = GERMAN ENCODING;
      65  static const char LOCALE3[] = FRENCH ENCODING;
      66  
      67  static char *expected;
      68  
      69  static void *
      70  thread1_func (void *arg)
      71  {
      72    for (;;)
      73      {
      74        char buf[SETLOCALE_NULL_ALL_MAX];
      75  
      76        if (setlocale_null_r (LC_ALL, buf, sizeof (buf)))
      77          abort ();
      78        if (strcmp (expected, buf) != 0)
      79          {
      80            fprintf (stderr, "thread1 disturbed by thread2!\n"); fflush (stderr);
      81            abort ();
      82          }
      83      }
      84  
      85    /*NOTREACHED*/
      86  }
      87  
      88  static void *
      89  thread2_func (void *arg)
      90  {
      91    for (;;)
      92      {
      93        char buf[SETLOCALE_NULL_ALL_MAX];
      94  
      95        setlocale_null_r (LC_NUMERIC, buf, sizeof (buf));
      96        setlocale_null_r (LC_ALL, buf, sizeof (buf));
      97      }
      98  
      99    /*NOTREACHED*/
     100  }
     101  
     102  int
     103  main (int argc, char *argv[])
     104  {
     105    if (setlocale (LC_ALL, LOCALE1) == NULL)
     106      {
     107        fprintf (stderr, "Skipping test: LOCALE1 not recognized\n");
     108        return 77;
     109      }
     110    if (setlocale (LC_NUMERIC, LOCALE2) == NULL)
     111      {
     112        fprintf (stderr, "Skipping test: LOCALE2 not recognized\n");
     113        return 77;
     114      }
     115    if (setlocale (LC_TIME, LOCALE3) == NULL)
     116      {
     117        fprintf (stderr, "Skipping test: LOCALE3 not recognized\n");
     118        return 77;
     119      }
     120  
     121    expected = strdup (setlocale (LC_ALL, NULL));
     122  
     123    /* Create the two threads.  */
     124    gl_thread_create (thread1_func, NULL);
     125    gl_thread_create (thread2_func, NULL);
     126  
     127    /* Let them run for 5 seconds.  */
     128    {
     129      struct timespec duration;
     130      duration.tv_sec = 5;
     131      duration.tv_nsec = 0;
     132  
     133      nanosleep (&duration, NULL);
     134    }
     135  
     136    return 0;
     137  }
     138  
     139  #else
     140  
     141  /* No multithreading available.  */
     142  
     143  #include <stdio.h>
     144  
     145  int
     146  main ()
     147  {
     148    fputs ("Skipping test: multithreading not enabled\n", stderr);
     149    return 77;
     150  }
     151  
     152  #endif
     153  
     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               crash < 1 sec
     170  mingw                OK
     171  MSVC                 OK (assuming compiler option /MD !)
     172  */