diff mbox series

[2/5] signal: Move sys_siglist to a compat symbol

Message ID 20200427214855.2523259-2-adhemerval.zanella@linaro.org
State New
Headers show
Series [v2,1/5] signal: Add signum-{generic,arch}.h | expand

Commit Message

Adhemerval Zanella April 27, 2020, 9:48 p.m. UTC
The symbol was deprecated by strsignal and its usage imposes issues
such as copy relocations.

Its internal name is changed to __sys_siglist_internal to avoid static
linking usage.  The compat code is also refactored, since both Linux
and Hurd usage the same strategy: export the same array with different
object sizes.

The libSegfault change avoids calling strsignal on the SIGFAULT signal
handler (the current usage is already sketchy, adding a call that
potentially issue locale internal function is even sketchier).

Checked on x86_64-linux-gnu and i686-linux-gnu. I also run a check-abi
on all affected platforms.
---
 NEWS                                          |  6 ++
 debug/segfault.c                              | 18 ++---
 include/signal.h                              |  2 +-
 signal/signal.h                               |  6 --
 stdio-common/psiginfo.c                       |  2 +-
 stdio-common/psignal.c                        |  2 +-
 stdio-common/siglist.c                        |  7 +-
 string/strsignal.c                            |  2 +-
 sysdeps/generic/siglist-compat.c              |  1 +
 sysdeps/generic/siglist-compat.h              | 47 +++++++++++
 sysdeps/gnu/siglist.c                         | 78 -------------------
 .../mach/hurd/{siglist.h => siglist-compat.c} | 13 +++-
 .../linux/{siglist.h => siglist-compat.c}     | 17 ++--
 13 files changed, 90 insertions(+), 111 deletions(-)
 create mode 100644 sysdeps/generic/siglist-compat.c
 create mode 100644 sysdeps/generic/siglist-compat.h
 delete mode 100644 sysdeps/gnu/siglist.c
 rename sysdeps/mach/hurd/{siglist.h => siglist-compat.c} (68%)
 rename sysdeps/unix/sysv/linux/{siglist.h => siglist-compat.c} (62%)

Comments

Florian Weimer April 28, 2020, 2:50 p.m. UTC | #1
* Adhemerval Zanella via Libc-alpha:

> diff --git a/signal/signal.h b/signal/signal.h
> index fa8de963f8..3739550e5f 100644
> --- a/signal/signal.h
> +++ b/signal/signal.h
> @@ -281,12 +281,6 @@ extern int sigqueue (__pid_t __pid, int __sig, const union sigval __val)
>  
>  #ifdef __USE_MISC
>  
> -/* Names of the signals.  This variable exists only for compatibility.
> -   Use `strsignal' instead (see <string.h>).  */
> -extern const char *const _sys_siglist[_NSIG];
> -extern const char *const sys_siglist[_NSIG];

This is yet another removal without a formal deprecation warning.  Do
we really want to do this?  mutt does not yet use strsignal, for
example.
Adhemerval Zanella April 28, 2020, 3 p.m. UTC | #2
On 28/04/2020 11:50, Florian Weimer wrote:
> * Adhemerval Zanella via Libc-alpha:
> 
>> diff --git a/signal/signal.h b/signal/signal.h
>> index fa8de963f8..3739550e5f 100644
>> --- a/signal/signal.h
>> +++ b/signal/signal.h
>> @@ -281,12 +281,6 @@ extern int sigqueue (__pid_t __pid, int __sig, const union sigval __val)
>>  
>>  #ifdef __USE_MISC
>>  
>> -/* Names of the signals.  This variable exists only for compatibility.
>> -   Use `strsignal' instead (see <string.h>).  */
>> -extern const char *const _sys_siglist[_NSIG];
>> -extern const char *const sys_siglist[_NSIG];
> 
> This is yet another removal without a formal deprecation warning.  Do
> we really want to do this?  mutt does not yet use strsignal, for
> example.
> 

At least for mutt, on the latest 1.13.5 version it will use sys_siglist
iff for !HAVE_STRERROR and its configure does check for strerror (on 
Linux HAVE_STRERROR will be set to 1).

In any case, I still think we should move sig_siglist to compat symbols.
Although its usage is mitigated by current trend to use PIE, copy
relocation are still problematic.  And it to fix mips NSIG definition
would require to add a net 2.32 compat version for the symbol, which
I really would like to avoid.
Florian Weimer April 28, 2020, 3:11 p.m. UTC | #3
* Adhemerval Zanella via Libc-alpha:

> On 28/04/2020 11:50, Florian Weimer wrote:
>> * Adhemerval Zanella via Libc-alpha:
>> 
>>> diff --git a/signal/signal.h b/signal/signal.h
>>> index fa8de963f8..3739550e5f 100644
>>> --- a/signal/signal.h
>>> +++ b/signal/signal.h
>>> @@ -281,12 +281,6 @@ extern int sigqueue (__pid_t __pid, int __sig, const union sigval __val)
>>>  
>>>  #ifdef __USE_MISC
>>>  
>>> -/* Names of the signals.  This variable exists only for compatibility.
>>> -   Use `strsignal' instead (see <string.h>).  */
>>> -extern const char *const _sys_siglist[_NSIG];
>>> -extern const char *const sys_siglist[_NSIG];
>> 
>> This is yet another removal without a formal deprecation warning.  Do
>> we really want to do this?  mutt does not yet use strsignal, for
>> example.
>> 
>
> At least for mutt, on the latest 1.13.5 version it will use sys_siglist
> iff for !HAVE_STRERROR and its configure does check for strerror (on 
> Linux HAVE_STRERROR will be set to 1).

sys_siglist and HAVE_STRERROR?  

I see this in the mutt 1.13.2 sources:

signal.c-73-/* Attempt to catch "ordinary" signals and shut down gracefully. */
signal.c-74-static void exit_handler (int sig)
signal.c-75-{
signal.c-76-  curs_set (1);
signal.c-77-  endwin (); /* just to be safe */
signal.c-78-
signal.c-79-  exit_print_string ("Caught signal ");
signal.c-80-#if SYS_SIGLIST_DECLARED
signal.c:81:  exit_print_string (sys_siglist[sig]);
signal.c-82-#else
signal.c-83-#if (__sun__ && __svr4__)
signal.c:84:  exit_print_string (_sys_siglist[sig]);
signal.c-85-#else
signal.c-86-#if (__alpha && __osf__)
signal.c:87:  exit_print_string (__sys_siglist[sig]);
signal.c-88-#else
signal.c-89-  exit_print_int (sig);
signal.c-90-#endif
signal.c-91-#endif
signal.c-92-#endif
signal.c-93-  exit_print_string ("...  Exiting.\n");
signal.c-94-  exit (0);
signal.c-95-}

The code in neomutt is different, but uses the same libc facilities.

> In any case, I still think we should move sig_siglist to compat symbols.
> Although its usage is mitigated by current trend to use PIE, copy
> relocation are still problematic.  And it to fix mips NSIG definition
> would require to add a net 2.32 compat version for the symbol, which
> I really would like to avoid.

Hmm.

Other thoughts on this?  The header clearly said to use strsignal.
Adhemerval Zanella April 28, 2020, 3:31 p.m. UTC | #4
On 28/04/2020 12:11, Florian Weimer wrote:
> * Adhemerval Zanella via Libc-alpha:
> 
>> On 28/04/2020 11:50, Florian Weimer wrote:
>>> * Adhemerval Zanella via Libc-alpha:
>>>
>>>> diff --git a/signal/signal.h b/signal/signal.h
>>>> index fa8de963f8..3739550e5f 100644
>>>> --- a/signal/signal.h
>>>> +++ b/signal/signal.h
>>>> @@ -281,12 +281,6 @@ extern int sigqueue (__pid_t __pid, int __sig, const union sigval __val)
>>>>  
>>>>  #ifdef __USE_MISC
>>>>  
>>>> -/* Names of the signals.  This variable exists only for compatibility.
>>>> -   Use `strsignal' instead (see <string.h>).  */
>>>> -extern const char *const _sys_siglist[_NSIG];
>>>> -extern const char *const sys_siglist[_NSIG];
>>>
>>> This is yet another removal without a formal deprecation warning.  Do
>>> we really want to do this?  mutt does not yet use strsignal, for
>>> example.
>>>
>>
>> At least for mutt, on the latest 1.13.5 version it will use sys_siglist
>> iff for !HAVE_STRERROR and its configure does check for strerror (on 
>> Linux HAVE_STRERROR will be set to 1).
> 
> sys_siglist and HAVE_STRERROR?  

My mistake, I confused with sys_errlist.

> 
> I see this in the mutt 1.13.2 sources:
> 
> signal.c-73-/* Attempt to catch "ordinary" signals and shut down gracefully. */
> signal.c-74-static void exit_handler (int sig)
> signal.c-75-{
> signal.c-76-  curs_set (1);
> signal.c-77-  endwin (); /* just to be safe */
> signal.c-78-
> signal.c-79-  exit_print_string ("Caught signal ");
> signal.c-80-#if SYS_SIGLIST_DECLARED
> signal.c:81:  exit_print_string (sys_siglist[sig]);
> signal.c-82-#else
> signal.c-83-#if (__sun__ && __svr4__)
> signal.c:84:  exit_print_string (_sys_siglist[sig]);
> signal.c-85-#else
> signal.c-86-#if (__alpha && __osf__)
> signal.c:87:  exit_print_string (__sys_siglist[sig]);
> signal.c-88-#else
> signal.c-89-  exit_print_int (sig);
> signal.c-90-#endif
> signal.c-91-#endif
> signal.c-92-#endif
> signal.c-93-  exit_print_string ("...  Exiting.\n");
> signal.c-94-  exit (0);
> signal.c-95-}

And on Linux it will be evaluated to:

  static void exit_handler (int sig)
  {
    curs_set (1);
    endwin ();

    exit_print_string ("Caught signal ");
  # 89 "../signal.c"
    exit_print_int (sig);



    exit_print_string ("...  Exiting.\n");
    exit (0);
  }

Since SYS_SIGLIST_DECLARED is not defined.  Not sure why exactly the
config is not setting it, since config.log does have
ac_cv_have_decl_sys_siglist=yes.

And even its usage is not fully portable (solaris11 defines as
_sys_siglist, AIX 73 does not provide it). So I am not sure if we
should continue provide for newly binaries.


> 
> The code in neomutt is different, but uses the same libc facilities.
> 
>> In any case, I still think we should move sig_siglist to compat symbols.
>> Although its usage is mitigated by current trend to use PIE, copy
>> relocation are still problematic.  And it to fix mips NSIG definition
>> would require to add a net 2.32 compat version for the symbol, which
>> I really would like to avoid.
> 
> Hmm.
> 
> Other thoughts on this?  The header clearly said to use strsignal.
>
Florian Weimer April 29, 2020, 10:10 a.m. UTC | #5
* Adhemerval Zanella:

>> I see this in the mutt 1.13.2 sources:
>> 
>> signal.c-73-/* Attempt to catch "ordinary" signals and shut down gracefully. */
>> signal.c-74-static void exit_handler (int sig)
>> signal.c-75-{
>> signal.c-76-  curs_set (1);
>> signal.c-77-  endwin (); /* just to be safe */
>> signal.c-78-
>> signal.c-79-  exit_print_string ("Caught signal ");
>> signal.c-80-#if SYS_SIGLIST_DECLARED
>> signal.c:81:  exit_print_string (sys_siglist[sig]);
>> signal.c-82-#else
>> signal.c-83-#if (__sun__ && __svr4__)
>> signal.c:84:  exit_print_string (_sys_siglist[sig]);
>> signal.c-85-#else
>> signal.c-86-#if (__alpha && __osf__)
>> signal.c:87:  exit_print_string (__sys_siglist[sig]);
>> signal.c-88-#else
>> signal.c-89-  exit_print_int (sig);
>> signal.c-90-#endif
>> signal.c-91-#endif
>> signal.c-92-#endif
>> signal.c-93-  exit_print_string ("...  Exiting.\n");
>> signal.c-94-  exit (0);
>> signal.c-95-}
>
> And on Linux it will be evaluated to:
>
>   static void exit_handler (int sig)
>   {
>     curs_set (1);
>     endwin ();
>
>     exit_print_string ("Caught signal ");
>   # 89 "../signal.c"
>     exit_print_int (sig);
>
>
>
>     exit_print_string ("...  Exiting.\n");
>     exit (0);
>   }
>
> Since SYS_SIGLIST_DECLARED is not defined.  Not sure why exactly the
> config is not setting it, since config.log does have
> ac_cv_have_decl_sys_siglist=yes.

Huh, this is surprising.  Maybe this got fixed in neomutt?

> And even its usage is not fully portable (solaris11 defines as
> _sys_siglist, AIX 73 does not provide it). So I am not sure if we
> should continue provide for newly binaries.

Another difference is that the variables are async-signal-safe.
strerror and strsignal might not be if the argument is out of range
(something that can be checked with the count variable in the other
case).  At least our strsignal is already thread-safe.

I'm going to propose errno_constant and signal_constant functions to
cover the async-signal-safe case.  Let's see if they gain positive
feedback from the larger libc community.

I will review your patch some time later this week.
Adhemerval Zanella April 29, 2020, 11:40 a.m. UTC | #6
On 29/04/2020 07:10, Florian Weimer wrote:
> * Adhemerval Zanella:
> 
>>> I see this in the mutt 1.13.2 sources:
>>>
>>> signal.c-73-/* Attempt to catch "ordinary" signals and shut down gracefully. */
>>> signal.c-74-static void exit_handler (int sig)
>>> signal.c-75-{
>>> signal.c-76-  curs_set (1);
>>> signal.c-77-  endwin (); /* just to be safe */
>>> signal.c-78-
>>> signal.c-79-  exit_print_string ("Caught signal ");
>>> signal.c-80-#if SYS_SIGLIST_DECLARED
>>> signal.c:81:  exit_print_string (sys_siglist[sig]);
>>> signal.c-82-#else
>>> signal.c-83-#if (__sun__ && __svr4__)
>>> signal.c:84:  exit_print_string (_sys_siglist[sig]);
>>> signal.c-85-#else
>>> signal.c-86-#if (__alpha && __osf__)
>>> signal.c:87:  exit_print_string (__sys_siglist[sig]);
>>> signal.c-88-#else
>>> signal.c-89-  exit_print_int (sig);
>>> signal.c-90-#endif
>>> signal.c-91-#endif
>>> signal.c-92-#endif
>>> signal.c-93-  exit_print_string ("...  Exiting.\n");
>>> signal.c-94-  exit (0);
>>> signal.c-95-}
>>
>> And on Linux it will be evaluated to:
>>
>>   static void exit_handler (int sig)
>>   {
>>     curs_set (1);
>>     endwin ();
>>
>>     exit_print_string ("Caught signal ");
>>   # 89 "../signal.c"
>>     exit_print_int (sig);
>>
>>
>>
>>     exit_print_string ("...  Exiting.\n");
>>     exit (0);
>>   }
>>
>> Since SYS_SIGLIST_DECLARED is not defined.  Not sure why exactly the
>> config is not setting it, since config.log does have
>> ac_cv_have_decl_sys_siglist=yes.
> 
> Huh, this is surprising.  Maybe this got fixed in neomutt?

No idea, I just downloaded the latest mutt code and try to build to
check its usage of the arrays. 

> 
>> And even its usage is not fully portable (solaris11 defines as
>> _sys_siglist, AIX 73 does not provide it). So I am not sure if we
>> should continue provide for newly binaries.
> 
> Another difference is that the variables are async-signal-safe.
> strerror and strsignal might not be if the argument is out of range
> (something that can be checked with the count variable in the other
> case).  At least our strsignal is already thread-safe.
> 

We have strerror_r at least as an extension.

> I'm going to propose errno_constant and signal_constant functions to
> cover the async-signal-safe case.  Let's see if they gain positive
> feedback from the larger libc community.

Instead I think it would be better just simplify glibc strerror
and strsignal assumptions to *not* return locale dependent messages
and add a strsignal_l for the case.

So strerror/strsignal will just directly access the underlying error
with the expected bound error checks and thus be asignal-safe.

> 
> I will review your patch some time later this week.
> 

Thanks.
Florian Weimer April 29, 2020, 11:57 a.m. UTC | #7
* Adhemerval Zanella:

>>> And even its usage is not fully portable (solaris11 defines as
>>> _sys_siglist, AIX 73 does not provide it). So I am not sure if we
>>> should continue provide for newly binaries.
>> 
>> Another difference is that the variables are async-signal-safe.
>> strerror and strsignal might not be if the argument is out of range
>> (something that can be checked with the count variable in the other
>> case).  At least our strsignal is already thread-safe.
>> 
>
> We have strerror_r at least as an extension.

It's not an extension, but GNU has a different prototype.  This makes
this interface really hard to use unfortunately.  Hence my desire for
a thread-safe strerror (which everyone assumes anyway).

>
>> I'm going to propose errno_constant and signal_constant functions to
>> cover the async-signal-safe case.  Let's see if they gain positive
>> feedback from the larger libc community.
>
> Instead I think it would be better just simplify glibc strerror
> and strsignal assumptions to *not* return locale dependent messages
> and add a strsignal_l for the case.
>
> So strerror/strsignal will just directly access the underlying error
> with the expected bound error checks and thus be asignal-safe.

There's still the formatting of unknown errors and signals.  I'm not
sure if we want to regress there.  (Userspace can sometimes see
invalid errors from kernel subsystems.)
Adhemerval Zanella April 29, 2020, 12:33 p.m. UTC | #8
On 29/04/2020 08:57, Florian Weimer wrote:
> * Adhemerval Zanella:
> 
>>>> And even its usage is not fully portable (solaris11 defines as
>>>> _sys_siglist, AIX 73 does not provide it). So I am not sure if we
>>>> should continue provide for newly binaries.
>>>
>>> Another difference is that the variables are async-signal-safe.
>>> strerror and strsignal might not be if the argument is out of range
>>> (something that can be checked with the count variable in the other
>>> case).  At least our strsignal is already thread-safe.
>>>
>>
>> We have strerror_r at least as an extension.
> 
> It's not an extension, but GNU has a different prototype.  This makes
> this interface really hard to use unfortunately.  Hence my desire for
> a thread-safe strerror (which everyone assumes anyway).

Indeed, but I think this is a different issue.  We have:

strerror           MT-unsafe   AS-Unsafe 
strerror_r (XSI)   MT-safe     AS-unsafe
strerror_r (GNU)   MT-safe     AS-unsafe
strerror_l         MT-safe     AS-unsafe

And I think we should do:

strerror           MT-unsafe   AS-safe 
strerror_r (XSI)   MT-safe     AS-safe
strerror_r (GNU)   MT-safe     AS-safe
strerror_l         MT-safe     AS-unsafe

By making strerror_r (which is used by both strerror and __xpg_strerror_r)
no translate the error messages.

As for strsignal, it would be trickier because it uses the allocated
buffer with __libc_once which might trigger malloc.  Maybe an option 
might to just follow the strerror and also provide a thread safe 
variant.  From:

strsignal          MT-safe     AS-unsafe

To:

strsignal          MT-unsafe   AS-safe
strsignal_r        MT-safe     AS-safe
strsignal_l        MT-safe     AS-unsafe

By also making strsignal not translate the error messages and not
fallback to allocate the internal buffer.

> 
>>
>>> I'm going to propose errno_constant and signal_constant functions to
>>> cover the async-signal-safe case.  Let's see if they gain positive
>>> feedback from the larger libc community.
>>
>> Instead I think it would be better just simplify glibc strerror
>> and strsignal assumptions to *not* return locale dependent messages
>> and add a strsignal_l for the case.
>>
>> So strerror/strsignal will just directly access the underlying error
>> with the expected bound error checks and thus be asignal-safe.
> 
> There's still the formatting of unknown errors and signals.  I'm not
> sure if we want to regress there.  (Userspace can sometimes see
> invalid errors from kernel subsystems.)
> 

It would be still formatted, but the default error message won't be
translated (as for other messages). I am not sure this characterize
a hard regression if the idea is to provide async-signal-safeness.
Florian Weimer April 29, 2020, 1:09 p.m. UTC | #9
* Adhemerval Zanella:

> On 29/04/2020 08:57, Florian Weimer wrote:
>> * Adhemerval Zanella:
>> 
>>>>> And even its usage is not fully portable (solaris11 defines as
>>>>> _sys_siglist, AIX 73 does not provide it). So I am not sure if we
>>>>> should continue provide for newly binaries.
>>>>
>>>> Another difference is that the variables are async-signal-safe.
>>>> strerror and strsignal might not be if the argument is out of range
>>>> (something that can be checked with the count variable in the other
>>>> case).  At least our strsignal is already thread-safe.
>>>>
>>>
>>> We have strerror_r at least as an extension.
>> 
>> It's not an extension, but GNU has a different prototype.  This makes
>> this interface really hard to use unfortunately.  Hence my desire for
>> a thread-safe strerror (which everyone assumes anyway).
>
> Indeed, but I think this is a different issue.  We have:
>
> strerror           MT-unsafe   AS-Unsafe 
> strerror_r (XSI)   MT-safe     AS-unsafe
> strerror_r (GNU)   MT-safe     AS-unsafe
> strerror_l         MT-safe     AS-unsafe
>
> And I think we should do:
>
> strerror           MT-unsafe   AS-safe 
> strerror_r (XSI)   MT-safe     AS-safe
> strerror_r (GNU)   MT-safe     AS-safe
> strerror_l         MT-safe     AS-unsafe
>
> By making strerror_r (which is used by both strerror and __xpg_strerror_r)
> no translate the error messages.

I think that's even more confusing than before because of the
different results between strerror, strerror_r, and strerror_l under
the same effective locale.

I have a proposal that will allow us to make strerror thread-safe:

  <http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2444.htm>

Then we can just forget about strerror_r.

> As for strsignal, it would be trickier because it uses the allocated
> buffer with __libc_once which might trigger malloc.  Maybe an option 
> might to just follow the strerror and also provide a thread safe 
> variant.  From:
>
> strsignal          MT-safe     AS-unsafe
>
> To:
>
> strsignal          MT-unsafe   AS-safe
> strsignal_r        MT-safe     AS-safe
> strsignal_l        MT-safe     AS-unsafe
>
> By also making strsignal not translate the error messages and not
> fallback to allocate the internal buffer.

Likewise, I don't think a non-thread-safe strsignal function is
useful.

The errno_constant and signal_constant functions would just provide
the names of the E* and SIG* constants, which seems more useful to me
than the different strings that implementations use even in the
English locale.
Adhemerval Zanella April 29, 2020, 1:52 p.m. UTC | #10
On 29/04/2020 10:09, Florian Weimer wrote:
> * Adhemerval Zanella:
> 
>> On 29/04/2020 08:57, Florian Weimer wrote:
>>> * Adhemerval Zanella:
>>>
>>>>>> And even its usage is not fully portable (solaris11 defines as
>>>>>> _sys_siglist, AIX 73 does not provide it). So I am not sure if we
>>>>>> should continue provide for newly binaries.
>>>>>
>>>>> Another difference is that the variables are async-signal-safe.
>>>>> strerror and strsignal might not be if the argument is out of range
>>>>> (something that can be checked with the count variable in the other
>>>>> case).  At least our strsignal is already thread-safe.
>>>>>
>>>>
>>>> We have strerror_r at least as an extension.
>>>
>>> It's not an extension, but GNU has a different prototype.  This makes
>>> this interface really hard to use unfortunately.  Hence my desire for
>>> a thread-safe strerror (which everyone assumes anyway).
>>
>> Indeed, but I think this is a different issue.  We have:
>>
>> strerror           MT-unsafe   AS-Unsafe 
>> strerror_r (XSI)   MT-safe     AS-unsafe
>> strerror_r (GNU)   MT-safe     AS-unsafe
>> strerror_l         MT-safe     AS-unsafe
>>
>> And I think we should do:
>>
>> strerror           MT-unsafe   AS-safe 
>> strerror_r (XSI)   MT-safe     AS-safe
>> strerror_r (GNU)   MT-safe     AS-safe
>> strerror_l         MT-safe     AS-unsafe
>>
>> By making strerror_r (which is used by both strerror and __xpg_strerror_r)
>> no translate the error messages.
> 
> I think that's even more confusing than before because of the
> different results between strerror, strerror_r, and strerror_l under
> the same effective locale.
> 
> I have a proposal that will allow us to make strerror thread-safe:
> 
>   <http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2444.htm>
> 
> Then we can just forget about strerror_r.

I recall reading you suggestion of per-thread state for the library 
implementation.  However I think what we are discussing here is another
issue, where translating the error messages is not directly related to
be standard allowing per-thread objects.

Bionic, for instance, seems to implement a async-safe-signal strerror
by 1. no translating the error message for both strerror and strerror_r
and 2. use a special format string snprintf-like routine.  And it also
seems to not care to implement translation routines for strerror_l.

And without resorting in translated messages it even easier to make it
async-safe since we could make the invalid error use a per-thread bounded
buffer instead of relying on malloc.

> 
>> As for strsignal, it would be trickier because it uses the allocated
>> buffer with __libc_once which might trigger malloc.  Maybe an option 
>> might to just follow the strerror and also provide a thread safe 
>> variant.  From:
>>
>> strsignal          MT-safe     AS-unsafe
>>
>> To:
>>
>> strsignal          MT-unsafe   AS-safe
>> strsignal_r        MT-safe     AS-safe
>> strsignal_l        MT-safe     AS-unsafe
>>
>> By also making strsignal not translate the error messages and not
>> fallback to allocate the internal buffer.
> 
> Likewise, I don't think a non-thread-safe strsignal function is
> useful.

Alright, I agree the strsignal_r indeed does not add much.  However
I do think that providing strsignal_l allows to provide a simple
async-signal-safe strsignal. 

> 
> The errno_constant and signal_constant functions would just provide
> the names of the E* and SIG* constants, which seems more useful to me
> than the different strings that implementations use even in the
> English locale.
> 

But if the idea is just to provide bounded access to internal
sys_{err,abrev,sig}list I don't think it is worth to add another set
of function if we can simplify the current ones.
diff mbox series

Patch

diff --git a/NEWS b/NEWS
index 0e627b3405..814903253f 100644
--- a/NEWS
+++ b/NEWS
@@ -26,6 +26,12 @@  Deprecated and removed features, and other changes affecting compatibility:
   but always fails with ENOSYS.  This reflects the removal of the system
   call from all architectures, starting with Linux 5.5.
 
+* The deprecated sys_siglist, _sys_siglist, and sys_sigabbrev arrays are
+  non longer available to newly linked binaries, and their declarations
+  have removed from from <string.h>.  They are exported solely as
+  compatibility symbols to support old binaries.  All programs should use
+  strsignal instead.
+
 Changes to build and runtime requirements:
 
   [Add changes to build and runtime requirements here]
diff --git a/debug/segfault.c b/debug/segfault.c
index 14c64cd0bd..8b59783c9e 100644
--- a/debug/segfault.c
+++ b/debug/segfault.c
@@ -49,20 +49,16 @@ 
 static const char *fname;
 
 
-/* We better should not use `strerror' since it can call far too many
-   other functions which might fail.  Do it here ourselves.  */
+/* Print the signal number SIGNAL.  Either strerror or strsignal might
+   call local internal functions and these in turn call far too many
+   other functions and might even allocate memory which might fail.  */
 static void
 write_strsignal (int fd, int signal)
 {
-  if (signal < 0 || signal >= _NSIG || _sys_siglist[signal] == NULL)
-    {
-      char buf[30];
-      char *ptr = _itoa_word (signal, &buf[sizeof (buf)], 10, 0);
-      WRITE_STRING ("signal ");
-      write (fd, buf, &buf[sizeof (buf)] - ptr);
-    }
-  else
-    WRITE_STRING (_sys_siglist[signal]);
+  char buf[30];
+  char *ptr = _itoa_word (signal, &buf[sizeof (buf)], 10, 0);
+  WRITE_STRING ("signal ");
+  write (fd, buf, &buf[sizeof (buf)] - ptr);
 }
 
 
diff --git a/include/signal.h b/include/signal.h
index 293258ad65..ce511cfe60 100644
--- a/include/signal.h
+++ b/include/signal.h
@@ -12,7 +12,7 @@  libc_hidden_proto (__sigpause)
 libc_hidden_proto (raise)
 libc_hidden_proto (__libc_current_sigrtmin)
 libc_hidden_proto (__libc_current_sigrtmax)
-libc_hidden_proto (_sys_siglist)
+extern const char *const __sys_siglist_internal[_NSIG] attribute_hidden;
 
 /* Now define the internal interfaces.  */
 extern __sighandler_t __bsd_signal (int __sig, __sighandler_t __handler);
diff --git a/signal/signal.h b/signal/signal.h
index fa8de963f8..3739550e5f 100644
--- a/signal/signal.h
+++ b/signal/signal.h
@@ -281,12 +281,6 @@  extern int sigqueue (__pid_t __pid, int __sig, const union sigval __val)
 
 #ifdef __USE_MISC
 
-/* Names of the signals.  This variable exists only for compatibility.
-   Use `strsignal' instead (see <string.h>).  */
-extern const char *const _sys_siglist[_NSIG];
-extern const char *const sys_siglist[_NSIG];
-
-
 /* Get machine-dependent `struct sigcontext' and signal subcodes.  */
 # include <bits/sigcontext.h>
 
diff --git a/stdio-common/psiginfo.c b/stdio-common/psiginfo.c
index 4d498d00aa..e7c3b6137e 100644
--- a/stdio-common/psiginfo.c
+++ b/stdio-common/psiginfo.c
@@ -80,7 +80,7 @@  psiginfo (const siginfo_t *pinfo, const char *s)
 
   const char *desc;
   if (pinfo->si_signo >= 0 && pinfo->si_signo < NSIG
-      && ((desc = _sys_siglist[pinfo->si_signo]) != NULL
+      && ((desc = __sys_siglist_internal[pinfo->si_signo]) != NULL
 #ifdef SIGRTMIN
 	  || (pinfo->si_signo >= SIGRTMIN && pinfo->si_signo < SIGRTMAX)
 #endif
diff --git a/stdio-common/psignal.c b/stdio-common/psignal.c
index de45e52734..20459a3bb0 100644
--- a/stdio-common/psignal.c
+++ b/stdio-common/psignal.c
@@ -34,7 +34,7 @@  psignal (int sig, const char *s)
   else
     colon = ": ";
 
-  if (sig >= 0 && sig < NSIG && (desc = _sys_siglist[sig]) != NULL)
+  if (sig >= 0 && sig < NSIG && (desc = __sys_siglist_internal[sig]) != NULL)
     (void) __fxprintf (NULL, "%s%s%s\n", s, colon, _(desc));
   else
     {
diff --git a/stdio-common/siglist.c b/stdio-common/siglist.c
index 04082594a0..34c32f9bc0 100644
--- a/stdio-common/siglist.c
+++ b/stdio-common/siglist.c
@@ -20,17 +20,18 @@ 
 #include <signal.h>
 #include <libintl.h>
 
-const char *const _sys_siglist[NSIG] =
+const char *const __sys_siglist_internal[NSIG] =
 {
 #define init_sig(sig, abbrev, desc)   [sig] = desc,
 #include <siglist.h>
 #undef init_sig
 };
 
-
-const char *const _sys_sigabbrev[NSIG] =
+const char *const __sys_sigabbrev_internal[NSIG] =
 {
 #define init_sig(sig, abbrev, desc)   [sig] = abbrev,
 #include <siglist.h>
 #undef init_sig
 };
+
+#include <siglist-compat.c>
diff --git a/string/strsignal.c b/string/strsignal.c
index 2843ffe39b..1551480026 100644
--- a/string/strsignal.c
+++ b/string/strsignal.c
@@ -51,7 +51,7 @@  strsignal (int signum)
       (signum >= SIGRTMIN && signum <= SIGRTMAX) ||
 #endif
       signum < 0 || signum >= NSIG
-      || (desc = _sys_siglist[signum]) == NULL)
+      || (desc = __sys_siglist_internal[signum]) == NULL)
     {
       char *buffer = getbuffer ();
       int len;
diff --git a/sysdeps/generic/siglist-compat.c b/sysdeps/generic/siglist-compat.c
new file mode 100644
index 0000000000..6e25b021ab
--- /dev/null
+++ b/sysdeps/generic/siglist-compat.c
@@ -0,0 +1 @@ 
+/* Empty.  */
diff --git a/sysdeps/generic/siglist-compat.h b/sysdeps/generic/siglist-compat.h
new file mode 100644
index 0000000000..b857efb9d7
--- /dev/null
+++ b/sysdeps/generic/siglist-compat.h
@@ -0,0 +1,47 @@ 
+/* Generic siglist compatibility macro definitions.
+   Copyright (C) 2020 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#ifndef _SIGLIST_COMPAT_H
+#define _SIGLIST_COMPAT_H
+
+#include <shlib-compat.h>
+#include <limits.h>
+
+/* Define new compat symbols for _sys_siglist, sys_siglist, and sys_sigabbrev
+   for version VERSION with NUMBERSIG times number of bytes per long int size.
+   Both _sys_siglist and sys_siglist alias to __sys_siglist_internal while
+   sys_sigabbrev alias to _sys_sigabbrev_internal.  Both target alias are
+   define in siglist.c.  */
+#define DEFINE_COMPAT_SIGLIST(NUMBERSIG, VERSION) 			     \
+  declare_symbol_alias (__ ## VERSION ## _sys_siglist,			     \
+			__sys_siglist_internal,				     \
+			object,	NUMBERSIG * (ULONG_WIDTH / UCHAR_WIDTH));    \
+  declare_symbol_alias (__ ## VERSION ## sys_siglist,			     \
+			__sys_siglist_internal,				     \
+			object,	NUMBERSIG * (ULONG_WIDTH / UCHAR_WIDTH));    \
+  declare_symbol_alias (__ ## VERSION ## _sys_sigabbrev,		     \
+			__sys_sigabbrev_internal,			     \
+			object, NUMBERSIG * (ULONG_WIDTH / UCHAR_WIDTH));    \
+  compat_symbol (libc, __## VERSION ## _sys_siglist,   _sys_siglist,	     \
+		 VERSION);						     \
+  compat_symbol (libc, __## VERSION ## sys_siglist,    sys_siglist,	     \
+		 VERSION);						     \
+  compat_symbol (libc, __## VERSION ## _sys_sigabbrev, sys_sigabbrev,	     \
+		 VERSION);						     \
+
+#endif
diff --git a/sysdeps/gnu/siglist.c b/sysdeps/gnu/siglist.c
deleted file mode 100644
index c24f356f21..0000000000
--- a/sysdeps/gnu/siglist.c
+++ /dev/null
@@ -1,78 +0,0 @@ 
-/* Define list of all signal numbers and their names.
-   Copyright (C) 1997-2020 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <https://www.gnu.org/licenses/>.  */
-
-#include <stddef.h>
-#include <signal.h>
-#include <libintl.h>
-#include <shlib-compat.h>
-#include <bits/wordsize.h>
-
-const char *const __new_sys_siglist[NSIG] =
-{
-#define init_sig(sig, abbrev, desc)   [sig] = desc,
-#include <siglist.h>
-#undef init_sig
-};
-libc_hidden_ver (__new_sys_siglist, _sys_siglist)
-
-const char *const __new_sys_sigabbrev[NSIG] =
-{
-#define init_sig(sig, abbrev, desc)   [sig] = abbrev,
-#include <siglist.h>
-#undef init_sig
-};
-
-#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)
-declare_symbol_alias (__old_sys_siglist, __new_sys_siglist, object,
-		      OLD_SIGLIST_SIZE * __WORDSIZE / 8)
-
-declare_symbol_alias (__old_sys_sigabbrev, __new_sys_sigabbrev, object,
-		      OLD_SIGLIST_SIZE * __WORDSIZE / 8)
-
-declare_symbol_alias (_old_sys_siglist, __new_sys_siglist, object,
-		      OLD_SIGLIST_SIZE * __WORDSIZE / 8)
-
-compat_symbol (libc, __old_sys_siglist, _sys_siglist, GLIBC_2_0);
-compat_symbol (libc, _old_sys_siglist, sys_siglist, GLIBC_2_0);
-compat_symbol (libc, __old_sys_sigabbrev, sys_sigabbrev, GLIBC_2_0);
-#endif
-
-#if SHLIB_COMPAT (libc, GLIBC_2_1, GLIBC_2_3_3) && defined OLD2_SIGLIST_SIZE
-declare_symbol_alias (__old2_sys_siglist, __new_sys_siglist, object,
-		      OLD2_SIGLIST_SIZE * __WORDSIZE / 8)
-
-declare_symbol_alias (__old2_sys_sigabbrev, __new_sys_sigabbrev, object,
-		      OLD2_SIGLIST_SIZE * __WORDSIZE / 8)
-
-declare_symbol_alias (_old2_sys_siglist, __new_sys_siglist, object,
-		      OLD2_SIGLIST_SIZE * __WORDSIZE / 8)
-
-compat_symbol (libc, __old2_sys_siglist, _sys_siglist, GLIBC_2_1);
-compat_symbol (libc, _old2_sys_siglist, sys_siglist, GLIBC_2_1);
-compat_symbol (libc, __old2_sys_sigabbrev, sys_sigabbrev, GLIBC_2_1);
-
-strong_alias (__new_sys_siglist, _new_sys_siglist)
-versioned_symbol (libc, __new_sys_siglist, _sys_siglist, GLIBC_2_3_3);
-versioned_symbol (libc, _new_sys_siglist, sys_siglist, GLIBC_2_3_3);
-versioned_symbol (libc, __new_sys_sigabbrev, sys_sigabbrev, GLIBC_2_3_3);
-#else
-strong_alias (__new_sys_siglist, _new_sys_siglist)
-versioned_symbol (libc, __new_sys_siglist, _sys_siglist, GLIBC_2_1);
-versioned_symbol (libc, _new_sys_siglist, sys_siglist, GLIBC_2_1);
-versioned_symbol (libc, __new_sys_sigabbrev, sys_sigabbrev, GLIBC_2_1);
-#endif
diff --git a/sysdeps/mach/hurd/siglist.h b/sysdeps/mach/hurd/siglist-compat.c
similarity index 68%
rename from sysdeps/mach/hurd/siglist.h
rename to sysdeps/mach/hurd/siglist-compat.c
index 2eee091610..c93f12366b 100644
--- a/sysdeps/mach/hurd/siglist.h
+++ b/sysdeps/mach/hurd/siglist-compat.c
@@ -1,4 +1,5 @@ 
-/* Copyright (C) 1999-2020 Free Software Foundation, Inc.
+/* Compatibility signal numbers and their names symbols.  Hurd version.
+   Copyright (C) 1997-2020 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -15,8 +16,12 @@ 
    License along with the GNU C Library; if not, see
    <https://www.gnu.org/licenses/>.  */
 
-/* This file is included multiple times.  */
+#include <siglist-compat.h>
 
-#include_next <siglist.h>	/* Get the canonical list.  */
+#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)
+DEFINE_COMPAT_SIGLIST (33, GLIBC_2_0)
+#endif
 
-#define	OLD_SIGLIST_SIZE	33 /* For GLIBC_2.0 binary compatibility.  */
+#if SHLIB_COMPAT (libc, GLIBC_2_1, GLIBC_2_32)
+DEFINE_COMPAT_SIGLIST (NSIG, GLIBC_2_1)
+#endif
diff --git a/sysdeps/unix/sysv/linux/siglist.h b/sysdeps/unix/sysv/linux/siglist-compat.c
similarity index 62%
rename from sysdeps/unix/sysv/linux/siglist.h
rename to sysdeps/unix/sysv/linux/siglist-compat.c
index 6ff2c613ad..c322326a99 100644
--- a/sysdeps/unix/sysv/linux/siglist.h
+++ b/sysdeps/unix/sysv/linux/siglist-compat.c
@@ -1,4 +1,5 @@ 
-/* Copyright (C) 1996-2020 Free Software Foundation, Inc.
+/* Compatibility signal numbers and their names symbols.  Linux version.
+   Copyright (C) 1997-2020 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -15,10 +16,16 @@ 
    License along with the GNU C Library; if not, see
    <https://www.gnu.org/licenses/>.  */
 
-/* This file is included multiple times.  */
+#include <siglist-compat.h>
 
-#include_next <siglist.h>	/* Get the canonical list.  */
+#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)
+DEFINE_COMPAT_SIGLIST (32, GLIBC_2_0)
+#endif
 
-#define	OLD_SIGLIST_SIZE	32 /* For GLIBC_2.0 binary compatibility.  */
+#if SHLIB_COMPAT (libc, GLIBC_2_1, GLIBC_2_3_3)
+DEFINE_COMPAT_SIGLIST (64, GLIBC_2_1)
+#endif
 
-#define OLD2_SIGLIST_SIZE	64 /* For GLIBC_2.1 binary compatibility.  */
+#if SHLIB_COMPAT (libc, GLIBC_2_3_3, GLIBC_2_32)
+DEFINE_COMPAT_SIGLIST (NSIG, GLIBC_2_3_3)
+#endif