Commit Graph

16 Commits

Author SHA1 Message Date
dab441aea2 always initialize thread pointer at program start
this is the first step in an overhaul aimed at greatly simplifying and
optimizing everything dealing with thread-local state.

previously, the thread pointer was initialized lazily on first access,
or at program startup if stack protector was in use, or at certain
random places where inconsistent state could be reached if it were not
initialized early. while believed to be fully correct, the logic was
fragile and non-obvious.

in the first phase of the thread pointer overhaul, support is retained
(and in some cases improved) for systems/situation where loading the
thread pointer fails, e.g. old kernels.

some notes on specific changes:

- the confusing use of libc.main_thread as an indicator that the
  thread pointer is initialized is eliminated in favor of an explicit
  has_thread_pointer predicate.

- sigaction no longer needs to ensure that the thread pointer is
  initialized before installing a signal handler (this was needed to
  prevent a situation where the signal handler caused the thread
  pointer to be initialized and the subsequent sigreturn cleared it
  again) but it still needs to ensure that implementation-internal
  thread-related signals are not blocked.

- pthread tsd initialization for the main thread is deferred in a new
  manner to minimize bloat in the static-linked __init_tp code.

- pthread_setcancelstate no longer needs special handling for the
  situation before the thread pointer is initialized. it simply fails
  on systems that cannot support a thread pointer, which are
  non-conforming anyway.

- pthread_cleanup_push/pop now check for missing thread pointer and
  nop themselves out in this case, so stdio no longer needs to avoid
  the cancellable path when the thread pointer is not available.

a number of cases remain where certain interfaces may crash if the
system does not support a thread pointer. at this point, these should
be limited to pthread interfaces, and the number of such cases should
be fewer than before.
2014-03-24 16:57:11 -04:00
d8b587796f mostly-cosmetic fixups to x32 port merge 2014-02-23 05:43:09 -05:00
3b168ce1fb use syscall_arg_t type for syscall prototypes in pthread code 2014-02-22 12:25:07 +01:00
73db33b949 remove leftover cp_sp cruft from cancellation code, fix small bug
the bug was that cancellation requests which arrived while a
cancellation point was interrupted by a signal handler would not be
acted upon when the signal handler returns. this was because cp_sp was
never set; it's no longer needed or used.

instead, just always re-raise the signal when cancellation was not
acted upon. this wastes a tiny amount of time in the rare case where
it even matters, but it ensures correctness and simplifies the code.
2012-05-25 00:35:09 -04:00
4da268f74b fix issue with longjmp out of signal handlers and cancellation
stale state information indicating that a thread was possibly blocked
at a cancellation point could get left behind if longjmp was used to
exit a signal handler that interrupted a cancellation point.

to fix the issue, we throw away the state information entirely and
simply compare the saved instruction pointer to a range of code
addresses in the __syscall_cp_asm function. all the ugly PIC work
(which becomes minimal anyway with this approach) is defered to
cancellation time instead of happening at every syscall, which should
improve performance too.

this commit also fixes cancellation on arm, which was mildly broken
(race condition, not checking cancellation flag once inside the
cancellation point zone). apparently i forgot to implement that. the
new arm code is untested, but appears correct; i'll test and fix it
later if there are problems.
2012-05-23 15:45:41 -04:00
ce7d72596c fix cancellation failure in single-threaded programs
even a single-threaded program can be cancellable, e.g. if it's called
pthread_cancel(pthread_self()). the correct predicate to check is not
whether multiple threads have been invoked, but whether pthread_self
has been invoked.
2012-01-22 17:19:37 -05:00
823813e3f4 fix crash in pthread_testcancel if pthread_self has not been called 2011-09-27 18:39:49 -04:00
188ebf51b4 close should not be cancellable after "failing" with EINTR
normally we allow cancellation to be acted upon when a syscall fails
with EINTR, since there is no useful status to report to the caller in
this case, and the signal that caused the interruption was almost
surely the cancellation request, anyway.

however, unlike all other syscalls, close has actually performed its
resource-deallocation function whenever it returns, even when it
returned an error. if we allow cancellation at this point, the caller
has no way of informing the program that the file descriptor was
closed, and the program may later try to close the file descriptor
again, possibly closing a different, newly-opened file.

the workaround looks ugly (special-casing one syscall), but it's
actually the case that close is the one and only syscall (at least
among cancellation points) with this ugly property.
2011-08-07 00:05:01 -04:00
98acf04fc0 use weak aliases rather than function pointers to simplify some code 2011-08-06 20:09:51 -04:00
344ea14885 fix breakage in cancellation due to signal functions overhaul
sigaddset was not accepting SIGCANCEL as a valid signal number.
2011-08-02 19:59:56 -04:00
be2e06d347 recheck cancellation disabled flag after syscall returns EINTR
we already checked before making the syscall, but it's possible that a
signal handler interrupted the blocking syscall and disabled
cancellation, and that this is the cause of EINTR. in this case, the
old behavior was testably wrong.
2011-04-18 20:50:37 -04:00
9080cc153c clean up handling of thread/nothread mode, locking 2011-04-17 16:53:54 -04:00
09dae2b7b6 fix bugs in cancellable syscall asm
x86_64 was just plain wrong in the cancel-flag-already-set path, and
crashing.

the more subtle error was not clearing the saved stack pointer before
returning to c code. this could result in the signal handler
misidentifying c code as the pre-syscall part of the asm, and acting
on cancellation at the wrong time, and thus resource leak race
conditions.

also, now __cancel (in the c code) is responsible for clearing the
saved sp in the already-cancelled branch. this means we have to use
call rather than jmp to ensure the stack pointer in the c will never
match what the asm saved.
2011-04-17 15:30:08 -04:00
02eff258c6 don't use pthread_once when there is no danger in race 2011-04-17 12:15:55 -04:00
e74664016b fix some minor issues in cancellation handling patch
signals were wrongly left masked, and cancellability state was not
switched to disabled, during the execution of cleanup handlers.
2011-04-17 12:09:47 -04:00
feee98903c overhaul pthread cancellation
this patch improves the correctness, simplicity, and size of
cancellation-related code. modulo any small errors, it should now be
completely conformant, safe, and resource-leak free.

the notion of entering and exiting cancellation-point context has been
completely eliminated and replaced with alternative syscall assembly
code for cancellable syscalls. the assembly is responsible for setting
up execution context information (stack pointer and address of the
syscall instruction) which the cancellation signal handler can use to
determine whether the interrupted code was in a cancellable state.

these changes eliminate race conditions in the previous generation of
cancellation handling code (whereby a cancellation request received
just prior to the syscall would not be processed, leaving the syscall
to block, potentially indefinitely), and remedy an issue where
non-cancellable syscalls made from signal handlers became cancellable
if the signal handler interrupted a cancellation point.

x86_64 asm is untested and may need a second try to get it right.
2011-04-17 11:43:03 -04:00