Revert the reversion and go with implementation described in cgf-000017, with

some modifications.
* init.cc (dll_entry): Revert previous change.
* miscfuncs.cc: Include sigproc.h for exit_thread declaration.
* winsup.h (ExitThread): Define as 'exit_thread' to ensure no accidental use.
* sigproc.cc (exit_thread): New function.
(wait_sig): Handle __SIGTHREADEXIT case.  Don't just block rather than
returning from this function.
* sigproc.h (__SIGTHREADEXIT): New enum.
(exit_thread): Declare.
* sync.cc (muto::release): Accept a tls command-line argument.
* sync.h (muto::release): Accept a tls command-line parameter.  Default to
&_my_tls.
* cygerrno.h (__set_errno): Define as extern so that no function code is ever
emitted.
* cygserver_ipc.h (cygserver_ipc.h): Ditto.
* miscfuncs.h (transform_chars): Ditto.
* path.h (has_attribute): Ditto.
* security.h (privilege_luid): Ditto.
* winsup.h (flush_file_buffers): Ditto.
This commit is contained in:
Christopher Faylor 2012-12-21 21:30:56 +00:00
parent 65068ebd7f
commit c3a4634985
13 changed files with 93 additions and 23 deletions

View File

@ -1,3 +1,28 @@
2012-12-21 Christopher Faylor <me.cygwin2012@cgf.cx>
Revert the reversion and go with implementation described in
cgf-000017, with some modifications.
* init.cc (dll_entry): Revert previous change.
* miscfuncs.cc: Include sigproc.h for exit_thread declaration.
* winsup.h (ExitThread): Define as 'exit_thread' to ensure no
accidental use.
* sigproc.cc (exit_thread): New function.
(wait_sig): Handle __SIGTHREADEXIT case. Don't just block rather than
returning from this function.
* sigproc.h (__SIGTHREADEXIT): New enum.
(exit_thread): Declare.
* sync.cc (muto::release): Accept a tls command-line argument.
* sync.h (muto::release): Accept a tls command-line parameter. Default
to &_my_tls.
* cygerrno.h (__set_errno): Define as extern so that no function code
is ever emitted.
* cygserver_ipc.h (cygserver_ipc.h): Ditto.
* miscfuncs.h (transform_chars): Ditto.
* path.h (has_attribute): Ditto.
* security.h (privilege_luid): Ditto.
* winsup.h (flush_file_buffers): Ditto.
2012-12-21 Christopher Faylor <me.cygwin2012@cgf.cx>
* DevNotes: Add entry cgf-000018.

View File

@ -22,7 +22,7 @@ int __stdcall geterrno_from_nt_status (NTSTATUS status, int deferrno = 13 /*EACC
#define __seterrno_from_win_error(val) seterrno_from_win_error (__FILE__, __LINE__, val)
#define __seterrno_from_nt_status(status) seterrno_from_nt_status (__FILE__, __LINE__, status)
inline int
extern inline int
__set_errno (const char *fn, int ln, int val)
{
debug_printf ("%s:%d setting errno %d", fn, ln, val);

View File

@ -33,7 +33,7 @@ struct proc {
#ifdef __INSIDE_CYGWIN__
#include "sigproc.h"
inline void
extern inline void
ipc_set_proc_info (proc &blk)
{
blk.cygpid = getpid ();

View File

@ -13,7 +13,6 @@ details. */
#include "cygtls.h"
#include "ntdll.h"
#include "shared_info.h"
#include "sync.h"
static DWORD _my_oldfunc;
@ -96,14 +95,7 @@ dll_entry (HANDLE h, DWORD reason, void *static_load)
if (dll_finished_loading
&& (PVOID) &_my_tls > (PVOID) &test_stack_marker
&& _my_tls.isinitialized ())
{
_my_tls.remove (0);
/* Make sure that we don't exit until the process has exited.
Otherwise there is a potential race where the thread exit
code could be considered to be the process exit code.
See cgf-000017 and cgf-000018 in DevNotes. */
lock_process here;
}
/* Windows 2000 has a bug in NtTerminateThread. Instead of releasing
the stack at teb->DeallocationStack it uses the value of
teb->Tib.StackLimit to evaluate the stack address. So we just claim

View File

@ -28,6 +28,7 @@ details. */
#include "cygheap.h"
#include "pinfo.h"
#include "exception.h"
#include "sigproc.h"
long tls_ix = -1;

View File

@ -31,7 +31,7 @@ void slashify (const char *, char *, bool);
#define isslash(c) ((c) == '/')
extern void transform_chars (PWCHAR, PWCHAR);
inline void
extern inline void
transform_chars (PUNICODE_STRING upath, USHORT start_idx)
{
transform_chars (upath->Buffer + start_idx,

View File

@ -18,7 +18,7 @@ details. */
#include <fcntl.h>
#include <alloca.h>
inline bool
extern inline bool
has_attribute (DWORD attributes, DWORD attribs_to_test)
{
return attributes != INVALID_FILE_ATTRIBUTES

View File

@ -354,13 +354,13 @@ extern cygpsid well_known_samba_unix_user_fake_sid;
bool privilege_luid (const PWCHAR pname, LUID &luid, bool &high_integrity);
inline BOOL
extern inline BOOL
well_known_sid_type (SID_NAME_USE type)
{
return type == SidTypeAlias || type == SidTypeWellKnownGroup;
}
inline BOOL
extern inline BOOL
legal_sid_type (SID_NAME_USE type)
{
return type == SidTypeUser || type == SidTypeGroup

View File

@ -553,6 +553,33 @@ sigproc_terminate (exit_states es)
}
}
/* Exit the current thread very carefully.
See cgf-000017 in DevNotes for more details on why this is
necessary. */
void
exit_thread (DWORD res)
{
HANDLE h;
if (!DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
GetCurrentProcess (), &h,
0, FALSE, DUPLICATE_SAME_ACCESS))
{
#ifdef DEBUGGING
system_printf ("couldn't duplicate the current thread, %E");
#endif
ExitThread (res);
}
ProtectHandle1 (h, exit_thread);
siginfo_t si = {__SIGTHREADEXIT, SI_KERNEL};
si.si_value.sival_ptr = h;
/* Tell wait_sig to wait for this thread to exit. It can then release
the lock below and close the above-opened handle. */
sig_send (myself_nowait, si, &_my_tls);
lock_process for_now;
ExitThread (0); /* Should never hit this */
}
int __stdcall
sig_send (_pinfo *p, int sig, _cygtls *tid)
{
@ -1419,6 +1446,23 @@ wait_sig (VOID *)
case __SIGSETPGRP:
init_console_handler (true);
break;
case __SIGTHREADEXIT:
{
/* Serialize thread exit as the thread exit code can be interpreted
as the process exit code in some cases when racing with
ExitProcess/TerminateProcess.
So, wait for the thread which sent this signal to exit, then
release the process lock which it held and close it's handle.
See cgf-000017 in DevNotes for more details.
*/
HANDLE h = (HANDLE) pack.si.si_value.sival_ptr;
DWORD res = WaitForSingleObject (h, 5000);
lock_process::force_release (pack.sigtls);
ForceCloseHandle1 (h, exit_thread);
if (res != WAIT_OBJECT_0)
system_printf ("WaitForSingleObject(%p) for thread exit returned %u", h, res);
}
break;
default:
if (pack.si.si_signo < 0)
sig_clear (-pack.si.si_signo);
@ -1461,5 +1505,8 @@ wait_sig (VOID *)
close_my_readsig ();
sigproc_printf ("signal thread exiting");
ExitThread (0);
/* Just wait for the process to go away. Otherwise, this thread's
exit value could be interpreted as the process exit value.
See cgf-000017 in DevNotes for more details. */
Sleep (INFINITE);
}

View File

@ -25,7 +25,8 @@ enum
__SIGHOLD = -(NSIG + 7),
__SIGNOHOLD = -(NSIG + 8),
__SIGEXIT = -(NSIG + 9),
__SIGSETPGRP = -(NSIG + 10)
__SIGSETPGRP = -(NSIG + 10),
__SIGTHREADEXIT = -(NSIG + 11)
};
#endif
@ -87,6 +88,7 @@ void __stdcall sigalloc ();
int kill_pgrp (pid_t, siginfo_t&);
int killsys (pid_t, int);
void exit_thread (DWORD) __attribute__ ((regparm (1), noreturn));
extern "C" void sigdelayed ();

View File

@ -4,7 +4,8 @@
which is intended to operate similarly to a mutex but attempts to
avoid making expensive calls to the kernel.
Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009, 2010 Red Hat, Inc.
Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009, 2010, 2011, 2012
Red Hat, Inc.
This file is part of Cygwin.
@ -109,10 +110,8 @@ muto::acquired ()
/* Return the muto lock. Needs to be called once per every acquire. */
int
muto::release ()
muto::release (_cygtls *this_tls)
{
void *this_tls = &_my_tls;
if (tls != this_tls || !visits)
{
SetLastError (ERROR_NOT_OWNER); /* Didn't have the lock. */

View File

@ -33,7 +33,7 @@ public:
~muto ()
#endif
int acquire (DWORD ms = INFINITE) __attribute__ ((regparm (2))); /* Acquire the lock. */
int release () __attribute__ ((regparm (1))); /* Release the lock. */
int release (_cygtls * = &_my_tls) __attribute__ ((regparm (2))); /* Release the lock. */
bool acquired () __attribute__ ((regparm (1)));
void upforgrabs () {tls = this;} // just set to an invalid address
@ -60,6 +60,7 @@ public:
if (!skip_unlock)
locker.release ();
}
static void force_release (_cygtls *tid) {locker.release (tid);}
friend class dtable;
friend class fhandler_fifo;
};

View File

@ -261,12 +261,15 @@ enum mmap_region_status
mmap_region_status mmap_is_attached_or_noreserve (void *addr, size_t len);
bool is_mmapped_region (caddr_t start_addr, caddr_t end_address);
inline bool flush_file_buffers (HANDLE h)
extern inline bool flush_file_buffers (HANDLE h)
{
return (GetFileType (h) != FILE_TYPE_PIPE) ? FlushFileBuffers (h) : true;
}
#define FlushFileBuffers flush_file_buffers
/* Make sure that regular ExitThread is never called */
#define ExitThread exit_thread
/**************************** Exports ******************************/
extern "C" {