From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on dcvr.yhbt.net X-Spam-Level: X-Spam-ASN: AS22989 209.51.188.0/24 X-Spam-Status: No, score=-3.7 required=3.0 tests=AWL,BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED,RCVD_IN_MSPIKE_H2,SPF_HELO_PASS,SPF_PASS shortcircuit=no autolearn=ham autolearn_force=no version=3.4.6 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dcvr.yhbt.net (Postfix) with ESMTPS id 774CD1F5A0 for ; Mon, 6 Feb 2023 16:37:00 +0000 (UTC) Authentication-Results: dcvr.yhbt.net; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=clisp.org header.i=@clisp.org header.a=rsa-sha256 header.s=strato-dkim-0002 header.b=fndjnZn/; dkim-atps=neutral Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pP4U6-0003Uf-D5; Mon, 06 Feb 2023 11:36:50 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pP4U3-0003UP-Ky for bug-gnulib@gnu.org; Mon, 06 Feb 2023 11:36:47 -0500 Received: from mo4-p00-ob.smtp.rzone.de ([85.215.255.22]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pP4U0-00020z-6J for bug-gnulib@gnu.org; Mon, 06 Feb 2023 11:36:47 -0500 ARC-Seal: i=1; a=rsa-sha256; t=1675701397; cv=none; d=strato.com; s=strato-dkim-0002; b=lEgbhfXZHGRdtrlIvN0VY3byodWIxnkGbIk2FcFbywR1qKVpVdLHAkMCmXkpJc4uBX cgcUDm+vgJKQAEMsVWZwhz/rLi0pj+MBj+vaU/gmlKecEUej6UpPw1nA6EqH7b7XgXod PeKhb3lOquPQXhvZggWzU3j1fForRwHidYtVi6DzTEmCjuop7ai1Yb17t3usuEqXpQH2 im7t3csjyd5QiYveBZ6s2aIX9LvBsCHUAw/VZ9jVwilLv54WzlNZOxcoOEpepXgMXMzp yGLGmOHR2ZzrYjJSBwdiZbzKoRMjWLWliMy04hlfwBgunQgEPUHdEkOXmtc7U7H7WiPR 2G5w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; t=1675701397; s=strato-dkim-0002; d=strato.com; h=References:In-Reply-To:Message-ID:Date:Subject:To:From:Cc:Date:From: Subject:Sender; bh=1T6wP/4ayRWHEZ2z/GG6eIgk2MTS2qCdhyT5ZI2Ukso=; b=m8A5WbEIc4dg4wvkHsx0W8o1LzGOnr642xBqtNy0jnzMG8AzPVmwQ4kGePgIcOuO3o KD75XnQFRtZu1pjw3SbT5Hz/XcY2ET5E7CEAoKYopCfXJYTiZNks9qeWYhl8r2gpxG5o HlkM9HlxHJVctHAAjM3Wn+1ksEcQ9r+GDVD1/YYIATeBFb6hXJQ4jNLtQPwRJv+SlpFq yvpPOEUQw/fwmbZqzJjrks3c14qdEumcgZsqKQ/LP7VPwl96JC8AM2bIDexpmiJnz4eD 04rAn415lVFt/IxtpfpOopLnALZ3y+XQMG2H2p6/eussc3AhSykZcuYNBHrRTJynrwLc zyEA== ARC-Authentication-Results: i=1; strato.com; arc=none; dkim=none X-RZG-CLASS-ID: mo00 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; t=1675701397; s=strato-dkim-0002; d=clisp.org; h=References:In-Reply-To:Message-ID:Date:Subject:To:From:Cc:Date:From: Subject:Sender; bh=1T6wP/4ayRWHEZ2z/GG6eIgk2MTS2qCdhyT5ZI2Ukso=; b=fndjnZn/W1jCoTAVG8AbACssxNZD1zXb9d1eEWmy60S5g3FyOb5f5YxdkrI2RsusE9 5kk6X6xACXYCSd6xqWk2b0hfxZmwbL81LltYhG6AWy/BxkVy/Heg9wP9GjhT2gwhYbtx FTqm6Iiidb6T9vmfqgPCM95l3uNvlvPueVU/NkW7hK3D67X7VH2aGncBnQ7tf2wYe8Vi dokzFSABOobYRPi2/TdM4a3CCM2GVYhy6mm/2mYRWkuII9WTEddOAATialRaah3o4Zqt 5uJj82NaIMRRIdw0rvGYEVZw7lxmWJKvxjMnK9+CQvcsnzbRQe2x/95vgdTdt2vXaA3L Yywg== X-RZG-AUTH: ":Ln4Re0+Ic/6oZXR1YgKryK8brlshOcZlIWs+iCP5vnk6shH0WWb0LN8XZoH94zq68+3cfpPF1PD+ezUIF+ECAUv0KY3UBImwtw==" Received: from nimes.localnet by smtp.strato.de (RZmta 49.2.2 AUTH) with ESMTPSA id 098542z16GabCht (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256 bits)) (Client did not present a certificate); Mon, 6 Feb 2023 17:36:37 +0100 (CET) From: Bruno Haible To: bug-gnulib@gnu.org, Corinna Vinschen Subject: Re: [PATCH] Do not decorate symbols as dllexport on Cygwin Date: Mon, 06 Feb 2023 17:36:36 +0100 Message-ID: <10831993.icLtTst4D9@nimes> In-Reply-To: References: <20230205194344.269174-1-vinschen@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: 7Bit Content-Type: text/plain; charset="us-ascii" Received-SPF: none client-ip=85.215.255.22; envelope-from=bruno@clisp.org; helo=mo4-p00-ob.smtp.rzone.de X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.001, SPF_HELO_PASS=-0.001, SPF_NONE=0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: bug-gnulib@gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gnulib discussion list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnulib-bounces+normalperson=yhbt.net@gnu.org Sender: bug-gnulib-bounces+normalperson=yhbt.net@gnu.org Hi Corinna, Sorry, I wanted to reply sooner. > > May I ask what's the idea to provide a thread-safe setlocale? It was > > never defined as thread-safe and POSIX explicitely mentions that. Any > > application expecting to call setlocale thread-safe is broken by design. The 'recode' package includes a shared library 'librecode', and shared libraries are supposed to be multithread-safe. Multithread-safe code is supposed to be able to obey the current locale, that is, - if uselocale(NULL) != LC_GLOBAL_LOCALE, uselocale() - if uselocale(NULL) == LC_GLOBAL_LOCALE, the global locale, that was last set through setlocale(). For example: - sprintf() needs to know the LC_CTYPE and LC_NUMERIC categories of the current locale, in order to transform wide strings via %ls or to format numbers via %f or %g. - iconv() needs to know the LC_CTYPE category of the current locale, for determining the appropriate transliterations. - strftime() needs to know the LC_TIME category of the current locale. - gettext() needs to know the LC_MESSAGES category of the current locale. All these functions are supposed to be writable in application code (if, for whatever reason, the sprintf, iconv, strftime, gettext functions in libc are not considered adequate). When POSIX specifies that applications cannot call setlocale() when there are multiple threads, this implies that in order to *inspect* the locale they need to do so before spawning the threads, and cache the value in a global variable, for later use. But this is not the application architecture that is in use when there are shared libraries. Shared libraries commonly don't have an initialization hook by which the application informs the library about the current locale for the rest of the execution of the process. So, conventional wisdom is to use setlocale(category, NULL). But this faces MT-safety problems. On some platforms the problem is that the setlocale(_, NULL) calls themselves will trash each other's data structures and thus provoke a crash. On other platforms the problem is that the return value produced in one thread is being clobbered by the second thread, and thus the first thread has no chance to copy the return value to a safe area in due time. For Cygwin, the problem until yesterday was the second one, for category == LC_ALL only. > > It should use the newlocale/duplocale/uselocale/freelocale API instead, > > isn't it? Even code that pays attention to the per-thread locale has to be prepared for the case that uselocale(NULL) returns LC_GLOBAL_LOCALE. In this case, the caller needs to fetch the values from the global locale. There is no locale_t object that could be queried in this case. > Ahhh, I finally see what's going on. The problem is not thread-safety > as such, but thread-safety when reading the value of the LC_ALL category. Yup, exactly. > Glibc's setlocale isn't entirely thread-safe either, but there's a > difference: > > - GLibc creates the global strings returned by setlocale(LC_xxx, NULL) > at the time the locale data is changed. All setlocale(LC_xxx, NULL) > calls only return pointer to strings created earlier. Yes. Thus each thread can be sure to be able to inspect the return value. (Assuming that there is no call to setlocale that *changes* the global locale. This is forbidden by POSIX, and reasonable applications don't do this.) > - Cygwin or, better, newlib, also return a pointer to global strings. > However, while the global strings for the specific categories are > created when the locale is changed, the string returned for LC_ALL > gets created on the fly when setlocale(LC_ALL, NULL) is called. ... and gets overwritten by another thread, since the buffer is not per-thread. > That's why test-setlocale_null-mt-all fails almost immediately. > > I created a patch to newlib's setlocale to tweak the LC_ALL string > each time the locale is changed, while setlocale(LC_ALL, NULL) > just returns the already prepared string. > > https://cygwin.com/git/?p=newlib-cygwin.git;a=commitdiff;h=23e49b18ce39 > > This patch will be in the next Cygwin release 3.4.6. Thanks a lot! I'm adjusting the Gnulib code now, accordingly. Bruno