(root)/
grep-3.11/
gnulib-tests/
test-setlocale_null-mt-one.c
       1  /* Multithread-safety test for setlocale_null_r (LC_xxx, ...).
       2     Copyright (C) 2019-2023 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_MAX];
      75  
      76        if (setlocale_null_r (LC_NUMERIC, 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_MAX];
      94  
      95        setlocale_null_r (LC_NUMERIC, buf, sizeof (buf));
      96        setlocale_null_r (LC_TIME, 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_NUMERIC, 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 2 seconds.  */
     128    {
     129      struct timespec duration;
     130      duration.tv_sec = 2;
     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            OK
     157  macOS                OK
     158  FreeBSD              OK
     159  NetBSD               OK
     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                OK
     169  Cygwin               OK
     170  mingw                OK
     171  MSVC                 OK (assuming compiler option /MD !)
     172  */