zsh-workers
 help / color / mirror / code / Atom feed
From: Peter Stephenson <p.w.stephenson@ntlworld.com>
To: zsh-workers@sunsite.dk
Cc: Guillaume Chazarain <guichaz@yahoo.fr>
Subject: Re: deadlock caused by gettext usage in a signal handler
Date: Mon, 3 Dec 2007 22:43:24 +0000	[thread overview]
Message-ID: <20071203224324.247fb30f.p.w.stephenson@ntlworld.com> (raw)
In-Reply-To: <20071130203534.1d1ea29c@inria.fr>

On Fri, 30 Nov 2007 20:35:34 +0100
Guillaume Chazarain <guichaz@yahoo.fr> wrote:
> I just had a Zsh process (using zsh-4.2.6-6.fc7) deadlock, the
> backtrace seems to show it is initializing the gettext infrastructure
> to print "Input/output error" in a signal handler.
> 
> As a solution, avoiding gettext() in signal handlers seems harder than
> forcing gettext() initialization before its first usage, but the cost
> may be prohibitive.

I'm not sure how we should handle this.  zsh doesn't ever use gettext()
directly and the interface it is using (strerror()) doesn't document
what needs to be initialised and when (nor even that it calls
gettext()).  I suppose a call to strerror() right at the top of the main
function might do the trick, but there's no guarantee and that seems
rather a hack.  Alternatively, we could use strerror_r() with, say, 80
characters off the stack, but there's no guarantee there aren't other
calls with the same problem.  So I can see possible things to do but
nothing that looks reliable.

I was going to say using strerror_r() was at least hack free, but it
turns out it isn't... there are two incompatible versions whose
prototypes differ only in return value, so it's difficult to test for
them.  So I've tried to handle both.  Yuk.  Suggestions welcome.

To get diff output for a test failure while I was writing this I needed
to use "diff -a" in ztst.zsh.  I'm not sure if the option is universal,
however.

Index: configure.ac
===================================================================
RCS file: /cvsroot/zsh/zsh/configure.ac,v
retrieving revision 1.82
diff -u -r1.82 configure.ac
--- configure.ac	24 Nov 2007 01:56:49 -0000	1.82
+++ configure.ac	3 Dec 2007 22:29:29 -0000
@@ -1157,7 +1157,7 @@
 	       getlogin getpwent getpwnam getpwuid getgrgid getgrnam \
 	       initgroups nis_list \
 	       setuid seteuid setreuid setresuid setsid \
-	       memcpy memmove strstr strerror \
+	       memcpy memmove strstr strerror strerror_r \
 	       getrlimit getrusage \
 	       setlocale \
 	       uname \
Index: Src/utils.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/utils.c,v
retrieving revision 1.171
diff -u -r1.171 utils.c
--- Src/utils.c	20 Nov 2007 09:55:10 -0000	1.171
+++ Src/utils.c	3 Dec 2007 22:29:31 -0000
@@ -255,6 +255,12 @@
 {
     const char *str;
     int num;
+#ifdef HAVE_STRERROR_R
+#define ERRBUFSIZE (80)
+    int olderrno;
+    char errbuf[ERRBUFSIZE];
+#endif
+    char *errmsg;
 
     if ((unset(SHINSTDIN) || locallevel) && lineno)
 	fprintf(file, "%ld: ", (long)lineno);
@@ -304,12 +310,39 @@
 		    errflag = 1;
 		    return;
 		}
+#ifdef HAVE_STRERROR_R
+		/*
+		 * There are two incompatible strerror_r()s floating round.
+		 * The GNU extension refuses to copy the message into the
+		 * buffer if it can return a constant string.  To suppress it
+		 * we need to define _XOPEN_SOURCE to 600.  I don't dare do
+		 * this because we're already depending on _GNU_SOURCE.  So
+		 * try to handle both by looking for errno being set (for the
+		 * standard version failing) or errbuf being left untouched
+		 * (for the GNU version).  One presumes that if strerror_r()
+		 * didn't copy anything to errbuf, then it's safe to
+		 * call strerror() to get the string.
+		 *
+		 * This is a mess, but it's about a decade and half
+		 * too late to shirk from messes in the source.
+		 */
+		olderrno = errno;
+		errno = 0;
+		errbuf[0] = '\0';
+		strerror_r(num, errbuf, ERRBUFSIZE);
+		if (errno || errbuf[0] == '\0')
+		    errmsg = strerror(num);
+		else
+		    errmsg = errbuf;
+		errno = olderrno;
+#else
+		errmsg = strerror(num);
+#endif
 		/* If the message is not about I/O problems, it looks better *
 		 * if we uncapitalize the first letter of the message        */
 		if (num == EIO)
-		    fputs(strerror(num), file);
+		    fputs(errmsg, file);
 		else {
-		    char *errmsg = strerror(num);
 		    fputc(tulower(errmsg[0]), file);
 		    fputs(errmsg + 1, file);
 		}


-- 
Peter Stephenson <p.w.stephenson@ntlworld.com>
Web page now at http://homepage.ntlworld.com/p.w.stephenson/


  reply	other threads:[~2007-12-03 22:43 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-11-30 19:35 Guillaume Chazarain
2007-12-03 22:43 ` Peter Stephenson [this message]
2007-12-04  1:39   ` Paul Ackersviller
2007-12-04 18:02   ` Guillaume Chazarain
2007-12-04 18:24     ` Peter Stephenson
2007-12-04 18:43       ` Guillaume Chazarain
2007-12-04 19:43         ` Peter Stephenson
2007-12-04 19:49           ` Guillaume Chazarain
2007-12-04 20:30 ` Peter Stephenson
2007-12-04 23:09   ` Guillaume Chazarain
2007-12-06 23:02   ` Guillaume Chazarain
2007-12-07 10:35     ` Peter Stephenson
2007-12-07 10:46       ` Guillaume Chazarain
2007-12-07 11:21         ` Bart Schaefer
2007-12-07 11:27           ` Peter Stephenson
2007-12-07 11:57             ` Guillaume Chazarain
2007-12-07 11:29         ` Peter Stephenson
2007-12-10  0:11 Paul Ackersviller
2007-12-10  2:04 ` Bart Schaefer
2007-12-10  3:17   ` Paul Ackersviller

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20071203224324.247fb30f.p.w.stephenson@ntlworld.com \
    --to=p.w.stephenson@ntlworld.com \
    --cc=guichaz@yahoo.fr \
    --cc=zsh-workers@sunsite.dk \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).