X-Recipient: archive-cygwin AT delorie DOT com X-SWARE-Spam-Status: No, hits=-3.6 required=5.0 tests=AWL,BAYES_00,RCVD_IN_DNSWL_LOW,SPF_HELO_PASS,SPF_PASS X-Spam-Check-By: sourceware.org To: cygwin AT cygwin DOT com From: Eric Blake Subject: fun? with libsigsegv Date: Fri, 17 Jul 2009 22:07:53 +0000 (UTC) Lines: 109 Message-ID: Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit User-Agent: Loom/3.14 (http://gmane.org/) X-IsSubscribed: yes Mailing-List: contact cygwin-help AT cygwin DOT com; run by ezmlm List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: cygwin-owner AT cygwin DOT com Mail-Followup-To: cygwin AT cygwin DOT com Delivered-To: mailing list cygwin AT cygwin DOT com This post is so cgf can exhale his bated breath from his recent commit: http://sourceware.org/cgi-bin/cvsweb.cgi/winsup/cygwin/cygtls.cc.diff? cvsroot=uberbaum&r1=1.68&r2=1.69 [By the way, that commit added changes to pipe handling without a ChangeLog entry; is it ready for prime-time yet?] First, the STC: $ cat foo.c #include #include #include #include #ifdef libsigsegv #include int handler (void *addr, int bad) { abort (); } #endif void die () { int i; i = fclose (stdout); fprintf (stderr, "fclose %d, errno %d\n", i, errno); errno = 0; i = fflush (stdout); fprintf (stderr, "fflush %d, errno %d\n", i, errno); } int main () { close (1); atexit (die); #ifdef libsigsegv sigsegv_install_handler (handler); #endif fputc ('1', stdout); return 0; } Pre-patch - this is with stock cygwin-1.7.0-51 and libsigsegv-2.4-1 (upstream libsigsegv is at 2.6, but I've checked that none of the upstream changes since 2.4 affect cygwin; it helps that I've written some of the upstream changes). In a way, the STC is relying on undefined behavior (POSIX says that the use of fflush(stdout) after fclose(stdout) is unspecified), but every other system I've tried handles this gracefully (although not consistently). $ gcc -o foo foo.c -lsigsegv $ ./foo fclose -1, errno 9 fflush 0, errno 0 No libsigsegv in the mix, and we don't detect any error (other platforms return -1 and/or set errno - the best would be doing both, rather than cygwin's approach of claiming success). Single stepping through fflush, it looks like we may be inadvertently faulting while dereferencing the closed stream, but that the fault is caught by cygwin (as part of _sigfe?) and silently ignored. $ gcc -o foo foo.c -lsigsegv -Dlibsigsegv $ ./foo fclose -1, errno 9 Aborted (core dumped) Ouch - adding libsigsegv into the mix meant that the internal fault is now trapped by libsigsegv before cygwin gets a chance to look at it, and turned into an abort. Proof positive that libsigsegv's mucking around with the SEH chain is not nice. Now, upgrade to the latest snapshot, 20090717. Without libsigsegv, things operate as before. But with libsigsegv, I now see... wait for it... (Sorry for dragging this on, but you DID say you were waiting with bated breath. :)... $ ./foo fclose -1, errno 9 fflush 0, errno 0 That is, libsigsegv no longer causes an unwanted abort. And the latest libsigsegv.git package still passes 'make check'. So in other words, it looks like you fixed a real bug, and without causing any regressions to libsigsegv (at least, none identified so far, although the upstream testsuite could probably test more cases)! Thanks! Meanwhile, I am considering working on a newlib patch that changes fflush to immediately die with EBADF rather than trying to _flockfile(fp) if fp->_flags is 0, if for no other reason than to be more like Linux in returning EBADF instead of success on my unspecified STC. -- Eric Blake -- Problem reports: http://cygwin.com/problems.html FAQ: http://cygwin.com/faq/ Documentation: http://cygwin.com/docs.html Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple