[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: hello-2.11 fails multibyte-1 and atexit-1 on musl
From: |
Sergei Trofimovich |
Subject: |
Re: hello-2.11 fails multibyte-1 and atexit-1 on musl |
Date: |
Sat, 29 Jan 2022 10:18:38 +0000 |
On Thu, 27 Jan 2022 22:08:57 +0000
Reuben Thomas <rrt@sc3d.org> wrote:
> On Wed, 26 Jan 2022 at 12:59, Sergei Trofimovich <slyich@gmail.com> wrote:
> >
>
> Thanks for the report!
>
> > From what I understand at
> >
> > https://wiki.musl-libc.org/functional-differences-from-glibc.html#Character-sets-and-locale
> > musl deliberately supports any char -> wchar_t (and back) conversion for
> > any char in LC_CTYPE=C. And thus the multibyte-1 test will always fail
> > there.
>
> I also found this problem on macOS. I tried on my GNU/Linux system
> using an ISO-8859 locale for the test, but the multibyte conversion
> does not fail! (e.g. in en_GB.iso88591). I also tried with
> ru_RU.KOI8-R, same result.
>
> It seems then that it's not going to be possible in general to find a
> locale that will fail. These results suggest that on some libc's,
> conversion will always succeed.
>
> Hence, I'm removing the test.
>
> > Not sure why atexit-1 fails. It seems to rely on
> > close_stdout_set_file_name() call in atexit(), but I don't see where in
> > code it's registered to call.
>
> Line 155 registers close_stdout. I can't see anything wrong with the
> way this is done; I'd be very grateful if you could investigate
> further.
Aha, I misinterpreted the atexit handler and did not notice
close_stdout_set_file_name() is part of gnulib.
Attached possible patch. Passes atexit-1 test on musl and glibc.
Some details:
The real reason to failure on musl is stream status and errno value
status in close_stream(). If I add a bit of fprintf() debugging it
becomes clearer:
void
close_stdout (void)
{
fprintf(stderr, "%s: errno=%d\n", __func__, errno);
if (close_stream (stdout) != 0
&& !(ignore_EPIPE && errno == EPIPE))
{
fprintf(stderr, "%s: after close_stream() errno=%d\n", __func__, errno);
...
Execution on glibc:
close_stdout: errno=0
close_stdout: after close_stream() errno=28
./hello: write error: No space left on device
Execution on glibc:
close_stdout: errno=28
close_stdout: after close_stream() errno=0
hello: write error
On glibc stdout flush did not happen yet by the time we get to atexit().
ltrace also gives the same hint:
On glibc:
$ ltrace ./hello
...
strlen("Hello, world!") = 13
malloc(56) = 0x10c78c0
mbsrtowcs(0x10c78c0, 0x7ffeb2b630a0, 14, 0x7ffeb2b630a8) = 13
wprintf(0x408298, 0x10c78c0, 177, 0) = 14
free(0x10c78c0) = <void>
exit(0 <unfinished ...>
__errno_location() = 0x7fa894ceb548
fprintf(0x7fa894cdf440, "%s: errno=%d\n", "close_stdout", 0close_stdout: errno=0
) = 22
__fpending(0x7fa894cdf520, 0x7ffeb2b609d0, 0, 0x7fa894c11343) = 14
ferror(0x7fa894cdf520) = 0
fclose(0x7fa894cdf520) = -1
fprintf(0x7fa894cdf440, "%s: after close_stream() errno=%"..., "close_stdout",
28close_stdout: after close_stream() errno=28
) = 44
dcgettext(0, 0x40836e, 5, 0x7fa894c11343) = 0x40836e
error(0, 28, 0x4080c8, 0x40836e./hello: write error: No space left on device
) = 0
_exit(1 <no return ...>
+++ exited (status 1) +++
Note that wprintf() queued 14 symbols successfully.
On musl queueing did not happen and thus stream close did not return error:
$ ltrace ./hello
...
strlen("Hello, world!") = 13
malloc(56) = 0x5570a96ddb10
mbsrtowcs(0x5570a96ddb10, 0x7ffdcb755398, 14, 0x7ffdcb7553a0) = 13
wprintf(0x5570a96d9298, 0x5570a96ddb10, 0xffffff3e, 1) = 0xffffffff
free(0x5570a96ddb10) = <void>
exit(0 <unfinished ...>
__errno_location() = 0x7fad63ed0b1c
fprintf(0x7fad63ece0c0, "%s: errno=%d\n", "close_stdout", 28close_stdout:
errno=28
) = 23
__fpending(0x7fad63ece2c0, 0x7ffdcb755040, 0xffffffff, 0) = 0
ferror(0x7fad63ece2c0) = 1
fclose(0x7fad63ece2c0) = 0
__errno_location() = 0x7fad63ed0b1c
fprintf(0x7fad63ece0c0, "%s: after close_stream() errno=%"..., "close_stdout",
0close_stdout: after close_stream() errno=0
) = 43
gettext(0x5570a96d92ba, 0x7ffdcb755040, 0xffffffff, 0) = 0x5570a96d92ba
fileno(0x7fad63ece2c0) = 1
fcntl(1, 3, 0x636f6c2f7273752f, 0x5570a96d92ba) = -1
fprintf(0x7fad63ece0c0, "%s: ", "hello"hello: ) = 7
vfprintf(0x7fad63ece0c0, "%s", 0x7ffdcb755230write error) = 11
putc(10, 0x7fad63ece0c0, 0xffffffff, 0
) = 10
fflush(0x7fad63ece0c0) = 0
_exit(1 <no return ...>
+++ exited (status 1) +++
On glibc write() happens in atexit:
$ strace ./hello
...
newfstatat(1, "", {st_mode=S_IFCHR|0666, st_rdev=makedev(0x1, 0x7), ...},
AT_EMPTY_PATH) = 0
ioctl(1, TCGETS, 0x7ffee70babb0) = -1 ENOTTY (Inappropriate ioctl for
device)
write(2, "close_stdout: errno=0\n", 22close_stdout: errno=0
) = 22
write(1, "Hello, world!\n", 14) = -1 ENOSPC (No space left on device)
close(1) = 0
write(2, "close_stdout: after close_stream"..., 44close_stdout: after
close_stream() errno=28
) = 44
write(2, "./hello: ", 9./hello: ) = 9
write(2, "write error", 11write error) = 11
On musl write() happens way before atexit, at main():
$ strace ./hello
...
writev(1, [{iov_base="Hello, world!", iov_len=13}, {iov_base="\n", iov_len=1}],
2) = -1 ENOSPC (No space left on device)
writev(2, [{iov_base="close_stdout: errno=28\n", iov_len=23}, {iov_base=NULL,
iov_len=0}], 2close_stdout: errno=28
) = 23
close(1) = 0
writev(2, [{iov_base="close_stdout: after close_stream"..., iov_len=43},
{iov_base=NULL, iov_len=0}], 2close_stdout: after close_stream() errno=0
) = 43
fcntl(1, F_GETFL) = -1 EBADF (Bad file descriptor)
writev(2, [{iov_base="hello: ", iov_len=7}, {iov_base=NULL, iov_len=0}],
2hello: ) = 7
writev(2, [{iov_base="write error", iov_len=11}, {iov_base=NULL, iov_len=0}],
2write error) = 11
writev(2, [{iov_base="", iov_len=0}, {iov_base="\n", iov_len=1}], 2
) = 1
exit_group(1) = ?
+++ exited with 1 +++
...
--
Sergei
0001-hello-force-stdout-buffering-until-atexit.patch
Description: Text Data