[PATCH 13/13] string: Add errname_np and errdesc_np
Adhemerval Zanella
adhemerval.zanella@linaro.org
Mon Jun 1 20:52:58 GMT 2020
On 28/05/2020 09:28, Florian Weimer wrote:
> * Adhemerval Zanella via Libc-alpha:
>
>> The errname_np returns error number name (i.g. "EINVAL" for EINVAL)
>> while errdescr_np returns string describing error number (i.g
>> "Invalid argument" for EINVAL). Different than strerror, errdescr_np
>> does not attempt to translate the return description and both functions
>> return NULL for an invalid error number.
>
> If you use a name that starts with "str", it's in the implementation
> namespace, and you don't need the _np suffix.
I don't have a strong preference here, maybe 'strerror_as'?
>
> Is errdescr_np really that useful? If yes, maybe we should define a
> global C locale object, similar to LC_GLOBAL_LOCALE, so that programmers
> can simply use strerror_l for this instead (except that it won't be
> async-signal-safe, hmm)?
The errdescr_np is added to provide the async-signal-safe strerror
analogous of the patch deprecated sys_errlist. The libSegfault itself
could use it, although I am not sure if async-safeness is really that
useful. It is way simpler than define a extra global C locale though.
>
>> diff --git a/manual/errno.texi b/manual/errno.texi
>> index 8cb4ce8b48..97ba3916ed 100644
>> --- a/manual/errno.texi
>> +++ b/manual/errno.texi
>> @@ -1207,6 +1207,28 @@ to @code{errno}.
>> The function @code{perror} is declared in @file{stdio.h}.
>> @end deftypefun
>>
>> +@deftypefun void errname_np (int @var{errnum})
>> +@standards{GNU, string.h}
>> +@safety{@prelim{}@mtsafe{@mtssigintr{}}@assafe{}@acsafe{}}
>> +This function returns the name describing the error @var{errnum} or
>> +@code{NULL} for invalid error number (i.g "EINVAL" for @code{EINVAL}).
>> +
>> +@pindex string.h
>> +This function is a GNU extension, declared in the header file @file{string.h}.
>> +@end deftypefun
>> +
>> +@deftypefun void errdesc_np (int @var{errnum})
>> +@standards{GNU, string.h}
>> +@safety{@prelim{}@mtsafe{@mtssigintr{}}@assafe{}@acsafe{}}
>> +This function returns the message describing the error @var{errnum} or
>> +@code{NULL} for invalid error number (i.g Invalid argument" for
>> +@code{EINVAL}). Different than @code{strerror} the returned description is
>> +not translated.
>> +
>> +@pindex string.h
>> +This function is a GNU extension, declared in the header file @file{string.h}.
>> +@end deftypefun
>
> Why @mtssigintr{} (twice)?
I am not following, each one annotates a different symbol (one for errname_np
and another for errdesc_np).
>
> I think error numbers for which no constant exist are still valid (in
> the C++ sense), so maybe we should phrase this differently: These
> functions return NULL if there is no known E* constant with this value.
Ack.
>
>> diff --git a/stdio-common/errlist.c b/stdio-common/errlist.c
>> index f7a49fbf35..dd078143f2 100644
>> --- a/stdio-common/errlist.c
>> +++ b/stdio-common/errlist.c
>> @@ -28,4 +28,12 @@ const char *const _sys_errlist_internal[] =
>>
>> const int _sys_nerr_internal = array_length (_sys_errlist_internal);
>>
>> +const char *const _sys_errname_internal[] =
>> + {
>> +/* This file is auto-generated from errlist.def. */
>> +#include <errlist-name.h>
>> + };
>> +
>> +const int _sys_nname_internal = array_length (_sys_errname_internal);
>> +
>> #include <errlist-compat.c>
>
> There should not be a reason to emit a separate constant for the length
> to the data segment. And we should eliminate the extra relocations this
> array adds. But I think we can add these changes later as an
> optimization.
Alright, I think it could be feasible to auto-generate both
_sys_errlist_internal and _sys_errname_internal with its expected size
(as we do for __sys_siglist_internal) and optimize the script to
emit the expected string size for each element.
>
>> diff --git a/stdio-common/test-err_np.c b/stdio-common/test-err_np.c
>> new file mode 100644
>> index 0000000000..b463c9f3ef
>> --- /dev/null
>> +++ b/stdio-common/test-err_np.c
>
> I would expect this test to compare against strerror and the E*
> constants directly. For the latter, we should generate a table
> containing elements like:
>
> { EINVAL, "EINVAL" },
The 'errname' does have this mapping. Should I add an extra test for
strerror as well?
>
>> diff --git a/string/_strerror.c b/string/_strerror.c
>> index 6ae8d47f0f..8bb9bfeaa9 100644
>> --- a/string/_strerror.c
>> +++ b/string/_strerror.c
>> @@ -24,14 +24,14 @@
>> char *
>> __strerror_r (int errnum, char *buf, size_t buflen)
>> {
>> - if (__glibc_unlikely (errnum < 0 || errnum >= _sys_nerr_internal
>> - || _sys_errlist_internal[errnum] == NULL))
>> + const char *r = __errdescr_np (errnum);
>> + if (r == NULL)
>> {
>> __snprintf (buf, buflen, "%s%d", _("Unknown error "), errnum);
>> return buf;
>> }
>>
>> - return (char *) _(_sys_errlist_internal[errnum]);
>> + return _(_sys_errlist_internal[errnum]);
>
> Shouldn't the last line re-use r?
It should, I have change it.
>
>> diff --git a/string/errname_np.c b/string/errname_np.c
>> new file mode 100644
>> index 0000000000..61455da219
>> --- /dev/null
>> +++ b/string/errname_np.c
>
>> +const char *const
>> +errname_np (int errnum)
>> +{
>> + const char *name = NULL;
>> +
>> + if (errnum >= 0 && errnum < _sys_nname_internal)
>> + name = _sys_errname_internal[errnum];
>> +
>> + return name;
>> +}
>
> I'm surprised that index 0 is looked up in the table.
It is defined a no error ('Success').
>
> It may make sense to move the definition of the array out ouf errlist.c,
> so that it can be shared across all ports.
On third patch on this set [1] I moved the generation to a script based
on errlist.def. Hurd requires its own version because it uses different
internal names (maybe we could cleanup this up later).
[1] https://sourceware.org/pipermail/libc-alpha/2020-May/113700.html
>
> Thanks,
> Florian
>
More information about the Libc-alpha
mailing list