perror() changes the orientation of stderr to byte-oriented mode if stderr is not oriented yet.

Corinna Vinschen corinna-cygwin@cygwin.com
Wed Jun 27 12:55:00 GMT 2018


Hi Takashi,



again, please send patches related to newlib to the newlib mailing list.
Newlib patches affect more targets than just Cygwin.  I redirected this
mail to the newlib list and attached your original attachments.  Thank
you.



On Jun 27 20:01, Takashi Yano wrote:
> POSIX states:
> The perror() function shall not change the orientation of the standard
> error stream.
> 
> However, cygwin perror() function changes the orientation of stderr to
> byte-oriented mode if stderr is not oriented yet.

That's newlib's perror actually.

> [...]
> I have made a patch to solve this problem, attached. However, I am not
> sure that calling _write_r() here is correct manner. I will appreciate
> if anyone familiar with libc code comment or make suggestions.

I'm not sure exactly.  It may be nice to keep the writes buffered
if the original stderr stream is buffered as well.

What about duplicating the non-_FVWRITE_IN_STREAMIO part of _fputs_r,
just without calling ORIENT?

Another solution might be what glibc does; if the stream has no
orientation yet, it duplicates the stderr FILE handle and uses that to
print the string.

Checking FreeBSD, it seems it actually calls writev, without actually
checking if the entire string has been written, see
https://github.com/freebsd/freebsd/blob/master/lib/libc/stdio/perror.c


Thanks,
Corinna

-- 
Corinna Vinschen                  Please, send mails regarding Cygwin to
Cygwin Maintainer                 cygwin AT cygwin DOT com
Red Hat
-------------- next part --------------
From cf56cf0eef8d48ca543aac96d57fdfebe3e8767a Mon Sep 17 00:00:00 2001
From: Takashi Yano <takashi.yano@nifty.ne.jp>
Date: Wed, 27 Jun 2018 19:26:15 +0900
Subject: [PATCH] Fix a bug of perror() which changes the orientation of
 stderr.

* perror.c: Fix the problem that perror() changes the orientation
  of stderr to byte-oriented mode if stderr is not oriented yet.
---
 newlib/libc/stdio/perror.c | 25 +++++++++++++++++++++----
 1 file changed, 21 insertions(+), 4 deletions(-)

diff --git a/newlib/libc/stdio/perror.c b/newlib/libc/stdio/perror.c
index d98e17e19..3328425da 100644
--- a/newlib/libc/stdio/perror.c
+++ b/newlib/libc/stdio/perror.c
@@ -58,6 +58,23 @@ Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>,
 #include <string.h>
 #include "local.h"
 
+static int
+write_err (struct _reent *ptr, const char *s)
+{
+  size_t len = strlen (s);
+  size_t len_out = 0;
+  int fd_err = fileno (_stderr_r (ptr));
+  while (len_out != len)
+    {
+      _ssize_t len1 = _write_r (ptr, fd_err, s+len_out, len-len_out);
+      if (len1 > 0)
+	len_out += len1;
+      else
+	return -1;
+    }
+  return 0;
+}
+
 void
 _perror_r (struct _reent *ptr,
        const char *s)
@@ -68,14 +85,14 @@ _perror_r (struct _reent *ptr,
   _REENT_SMALL_CHECK_INIT (ptr);
   if (s != NULL && *s != '\0')
     {
-      fputs (s, _stderr_r (ptr));
-      fputs (": ", _stderr_r (ptr));
+      write_err (ptr, s);
+      write_err (ptr, ": ");
     }
 
   if ((error = _strerror_r (ptr, ptr->_errno, 1, &dummy)) != NULL)
-    fputs (error, _stderr_r (ptr));
+    write_err (ptr, error);
 
-  fputc ('\n', _stderr_r (ptr));
+  write_err (ptr, "\n");
 }
 
 #ifndef _REENT_ONLY
-- 
2.17.0

-------------- next part --------------
#include <stdio.h>
#include <wchar.h>
#include <locale.h>
#include <errno.h>

int main()
{
	setlocale(LC_CTYPE, "de_DE.UTF-8");
	errno = EINVAL;
	printf("%d\n", fwide(stderr, 0));
	perror("äöü");
	printf("%d\n", fwide(stderr, 0));
	fwprintf(stderr, L"äöü\n");
	printf("%d\n", fwide(stderr, 0));
	perror("äöü");
	return 0;
}

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://sourceware.org/pipermail/newlib/attachments/20180627/7f712239/attachment.sig>


More information about the Newlib mailing list