From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 3200 invoked by alias); 5 Jun 2010 07:18:56 -0000 Received: (qmail 3102 invoked by uid 48); 5 Jun 2010 07:18:39 -0000 Date: Sat, 05 Jun 2010 07:18:00 -0000 From: "ceggers at gmx dot de" To: glibc-bugs@sources.redhat.com Message-ID: <20100605071837.11670.ceggers@gmx.de> Reply-To: sourceware-bugzilla@sourceware.org Subject: [Bug nptl/11670] New: Variables defined in pthread_cleanup_push() macro may be optimised away which breaks __sigsetjmp X-Bugzilla-Reason: CC Mailing-List: contact glibc-bugs-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Post: List-Help: , Sender: glibc-bugs-owner@sourceware.org X-SW-Source: 2010-06/txt/msg00069.txt.bz2 Please consider the following code snippset: --- snipp --- my_ptr = malloc(100); pthread_cleanup_push(my_handler, my_ptr); ... pthread_cleanup_pop(1); --- /snipp --- With -Os optimisation, the C equivalent of the optimised code can look similar to this (pure C, __EXCEPTIONS not defined): --- snipp --- /* # define pthread_cleanup_push(routine, arg) */ do { __pthread_unwind_buf_t __cancel_buf; [OPTIMISED AWAY]void (*__cancel_routine) (void *) = (routine); void *__cancel_arg = (arg); int not_first_call = __sigsetjmp ((struct __jmp_buf_tag *) (void *) __cancel_buf.__cancel_jmp_buf, 0); if (__builtin_expect (not_first_call, 0)) { my_handler (__cancel_arg); [__cancel_routine has been replaced by a fixed function call] __pthread_unwind_next (&__cancel_buf); /* NOTREACHED */ } __pthread_register_cancel (&__cancel_buf); do { ... [somewhere here the stack memory for __cancel_arg is "reused" by another variable, because ...] ... /* # define pthread_cleanup_pop(execute) */ do { } while (0);/* Empty to allow label before pthread_cleanup_pop. */ } while (0); __pthread_unregister_cancel (&__cancel_buf); if (execute) my_handler (my_ptr); [... __cancel_arg has been merged with my_ptr] } while (0) --- /snipp --- The compiler seems to recognize that the content of my_ptr and __cancel_arg is always the same, so there's no need to keep both on the stack. __cancel_arg in pthread_cleanup_pop() is replaced by my_ptr. As long as no cancellation happens everything is fine. my_handler() is always called with the correct argument. But in case of cancellation siglongjmp() may be called from a position after the stack memory for __cancel_arg has been "reused". In this case __sigsetjmp() returns and my_handler() is called with something different than the original value of my_ptr. The problem is not limited to __cancel_arg, the same could also happen to __cancel_buf or __cancel_routine (if not replaced by a fixed function call). I think there's no guarantee that none of the three stack variables is discarded between __pthread_register_cancel() and __pthread_unregister_cancel(). As a first try to solve this I've modified the macros so that they are more similar to the variant used when __EXCEPTIONS is defined (using the __cleanup__ attribute from GCC). The result seems to work for me, but it's in the nature of compiler optimisations that problems seems to be "disappeared" if something is altered a little bit ... -- Summary: Variables defined in pthread_cleanup_push() macro may be optimised away which breaks __sigsetjmp Product: glibc Version: 2.12 Status: NEW Severity: normal Priority: P2 Component: nptl AssignedTo: drepper at redhat dot com ReportedBy: ceggers at gmx dot de CC: glibc-bugs at sources dot redhat dot com GCC build triplet: x86_64-unknown-linux-gnu GCC host triplet: x86_64-unknown-linux-gnu GCC target triplet: arm-arm920t-linux-gnueabi http://sourceware.org/bugzilla/show_bug.cgi?id=11670 ------- You are receiving this mail because: ------- You are on the CC list for the bug, or are watching someone who is.