From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 11073 invoked from network); 3 Dec 2007 22:43:46 -0000 X-Spam-Checker-Version: SpamAssassin 3.2.3 (2007-08-08) on f.primenet.com.au X-Spam-Level: X-Spam-Status: No, score=-2.6 required=5.0 tests=AWL,BAYES_00 autolearn=ham version=3.2.3 Received: from news.dotsrc.org (HELO a.mx.sunsite.dk) (130.225.247.88) by ns1.primenet.com.au with SMTP; 3 Dec 2007 22:43:46 -0000 Received-SPF: none (ns1.primenet.com.au: domain at sunsite.dk does not designate permitted sender hosts) Received: (qmail 54452 invoked from network); 3 Dec 2007 22:43:40 -0000 Received: from sunsite.dk (130.225.247.90) by a.mx.sunsite.dk with SMTP; 3 Dec 2007 22:43:40 -0000 Received: (qmail 22962 invoked by alias); 3 Dec 2007 22:43:36 -0000 Mailing-List: contact zsh-workers-help@sunsite.dk; run by ezmlm Precedence: bulk X-No-Archive: yes X-Seq: 24148 Received: (qmail 22937 invoked from network); 3 Dec 2007 22:43:35 -0000 Received: from news.dotsrc.org (HELO a.mx.sunsite.dk) (130.225.247.88) by sunsite.dk with SMTP; 3 Dec 2007 22:43:35 -0000 Received: (qmail 54217 invoked from network); 3 Dec 2007 22:43:35 -0000 Received: from mtaout03-winn.ispmail.ntl.com (81.103.221.49) by a.mx.sunsite.dk with SMTP; 3 Dec 2007 22:43:29 -0000 Received: from aamtaout03-winn.ispmail.ntl.com ([81.103.221.35]) by mtaout03-winn.ispmail.ntl.com with ESMTP id <20071203224353.KEKV26125.mtaout03-winn.ispmail.ntl.com@aamtaout03-winn.ispmail.ntl.com>; Mon, 3 Dec 2007 22:43:53 +0000 Received: from pws-pc.ntlworld.com ([82.6.96.116]) by aamtaout03-winn.ispmail.ntl.com with SMTP id <20071203224409.JIMB26699.aamtaout03-winn.ispmail.ntl.com@pws-pc.ntlworld.com>; Mon, 3 Dec 2007 22:44:09 +0000 Date: Mon, 3 Dec 2007 22:43:24 +0000 From: Peter Stephenson To: zsh-workers@sunsite.dk Cc: Guillaume Chazarain Subject: Re: deadlock caused by gettext usage in a signal handler Message-Id: <20071203224324.247fb30f.p.w.stephenson@ntlworld.com> In-Reply-To: <20071130203534.1d1ea29c@inria.fr> References: <20071130203534.1d1ea29c@inria.fr> X-Mailer: Sylpheed 2.3.1 (GTK+ 2.10.14; x86_64-redhat-linux-gnu) Mime-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit On Fri, 30 Nov 2007 20:35:34 +0100 Guillaume Chazarain 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 Web page now at http://homepage.ntlworld.com/p.w.stephenson/