diff options
Diffstat (limited to 'winsup/cygwin/debug.cc')
-rw-r--r-- | winsup/cygwin/debug.cc | 299 |
1 files changed, 87 insertions, 212 deletions
diff --git a/winsup/cygwin/debug.cc b/winsup/cygwin/debug.cc index e8293b91f..418f35510 100644 --- a/winsup/cygwin/debug.cc +++ b/winsup/cygwin/debug.cc @@ -1,200 +1,66 @@ /* debug.cc - Copyright 1998, 1999, 2000, 2001 Red Hat, Inc. + Copyright 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. This software is a copyrighted work licensed under the terms of the Cygwin license. Please consult the file "CYGWIN_LICENSE" for details. */ #include "winsup.h" -#include "exceptions.h" #include "sync.h" #include "sigproc.h" #include "pinfo.h" #include "perthread.h" #include "perprocess.h" #include "security.h" +#include "cygerrno.h" +#ifdef DEBUGGING +#include <errno.h> +#include "fhandler.h" +#include "path.h" +#include "dtable.h" +#include "cygheap.h" +#endif #undef CloseHandle -static muto NO_COPY *threadname_lock = NULL; -#define lock_threadname() \ - do {if (threadname_lock) threadname_lock->acquire (INFINITE); } while (0) - -#define unlock_threadname() \ - do {if (threadname_lock) threadname_lock->release (); } while (0) - -typedef struct - { - DWORD id; - const char *name; - } thread_info; - -static NO_COPY thread_info threads[32] = {{0, NULL}}; // increase as necessary -#define NTHREADS (sizeof (threads) / sizeof (threads[0])) - -void -threadname_init () -{ - threadname_lock = new_muto (FALSE, "threadname_lock"); -} - -void __stdcall -regthread (const char *name, DWORD tid) -{ - lock_threadname (); - for (DWORD i = 0; i < NTHREADS; i++) - if (threads[i].name == NULL || strcmp (threads[i].name, name) == 0 || - threads[i].id == tid) - { - threads[i].name = name; - threads[i].id = tid; - break; - } - unlock_threadname (); -} - -int __stdcall -iscygthread () -{ - DWORD tid = GetCurrentThreadId (); - if (tid != mainthread.id) - for (DWORD i = 0; i < NTHREADS && threads[i].name != NULL; i++) - if (threads[i].id == tid) - return 1; - return 0; -} - -struct thread_start - { - LONG notavail; - LPTHREAD_START_ROUTINE func; - VOID *arg; - }; - -/* A place to store arguments to thread_stub since they can't be - stored on the stack. An available element is !notavail. */ -thread_start NO_COPY start_buf[NTHREADS] = {{0, NULL,NULL}}; - -/* Initial stub called by makethread. Performs initial per-thread - initialization. */ -static DWORD WINAPI -thread_stub (VOID *arg) -{ - LPTHREAD_START_ROUTINE threadfunc = ((thread_start *) arg)->func; - VOID *threadarg = ((thread_start *) arg)->arg; - - exception_list except_entry; - - /* Give up our slot in the start_buf array */ - (void) InterlockedExchange (&((thread_start *) arg)->notavail, 0); - - /* Initialize this thread's ability to respond to things like - SIGSEGV or SIGFPE. */ - init_exceptions (&except_entry); - - set_reent (user_data->impure_ptr); - ExitThread (threadfunc (threadarg)); -} - -/* Wrapper for CreateThread. Registers the thread name/id and ensures that - cygwin threads are properly initialized. */ -HANDLE __stdcall -makethread (LPTHREAD_START_ROUTINE start, LPVOID param, DWORD flags, - const char *name) -{ - DWORD tid; - HANDLE h; - thread_start *info; /* Various information needed by the newly created thread */ - - for (;;) - { - /* Search the start_buf array for an empty slot to use */ - for (info = start_buf; info < start_buf + NTHREADS; info++) - if (!InterlockedExchange (&info->notavail, 1)) - goto out; - - /* Should never hit here, but be defensive anyway. */ - Sleep (0); - } - -out: - info->func = start; /* Real function to start */ - info->arg = param; /* The single parameter to the thread */ - - if ((h = CreateThread (&sec_none_nih, 0, thread_stub, (VOID *) info, flags, - &tid))) - regthread (name, tid); /* Register for debugging output. */ - - return h; -} - -/* Return the symbolic name of the current thread for debugging. - */ -const char * __stdcall -threadname (DWORD tid, int lockit) -{ - const char *res = NULL; - if (!tid) - tid = GetCurrentThreadId (); - - if (lockit) - lock_threadname (); - for (DWORD i = 0; i < NTHREADS && threads[i].name != NULL; i++) - if (threads[i].id == tid) - { - res = threads[i].name; - break; - } - if (lockit) - unlock_threadname (); - - if (!res) - { - static char buf[30] NO_COPY = {0}; - __small_sprintf (buf, "unknown (%p)", tid); - res = buf; - } - - return res; -} - #ifdef DEBUGGING /* Here lies extra debugging routines which help track down internal Cygwin problems when compiled with -DDEBUGGING . */ #include <stdlib.h> +#define NFREEH (sizeof (cygheap->debug.freeh) / sizeof (cygheap->debug.freeh[0])) -typedef struct _h +class lock_debug +{ + static muto *locker; + bool acquired; + public: + lock_debug () : acquired (0) { - BOOL allocated; - HANDLE h; - const char *name; - const char *func; - int ln; - DWORD clexec_pid; - struct _h *next; - } handle_list; - -static NO_COPY handle_list starth = {0, NULL, NULL, NULL, 0, 0, NULL}; -static NO_COPY handle_list *endh = NULL; - -static handle_list NO_COPY freeh[1000] = {{0, NULL, NULL, NULL, 0, 0, NULL}}; -#define NFREEH (sizeof (freeh) / sizeof (freeh[0])) - -static muto NO_COPY *debug_lock = NULL; - -#define lock_debug() \ - do {if (debug_lock) debug_lock->acquire (INFINITE); } while (0) + if (locker) + acquired = !!locker->acquire (INFINITE); + } + void unlock () + { + if (locker && acquired) + { + locker->release (); + acquired = false; + } + } + ~lock_debug () {unlock ();} + friend void debug_init (); +}; -#define unlock_debug() \ - do {if (debug_lock) debug_lock->release (); } while (0) +muto NO_COPY *lock_debug::locker = NULL; static bool __stdcall mark_closed (const char *, int, HANDLE, const char *, BOOL); void debug_init () { - debug_lock = new_muto (FALSE, "debug_lock"); + muto *debug_lock_muto; + lock_debug::locker = new_muto (debug_lock_muto); } /* Find a registered handle in the linked list of handles. */ @@ -202,68 +68,68 @@ static handle_list * __stdcall find_handle (HANDLE h) { handle_list *hl; - for (hl = &starth; hl->next != NULL; hl = hl->next) + for (hl = &cygheap->debug.starth; hl->next != NULL; hl = hl->next) if (hl->next->h == h) goto out; - endh = hl; + cygheap->debug.endh = hl; hl = NULL; out: return hl; } +#ifdef DEBUGGING_AND_FDS_PROTECTED void -setclexec_pid (HANDLE h, bool setit) +setclexec (HANDLE oh, HANDLE nh, bool not_inheriting) { - handle_list *hl = find_handle (h); + handle_list *hl = find_handle (oh); if (hl) - hl->clexec_pid = setit ? GetCurrentProcessId () : 0; + { + hl = hl->next; + hl->inherited = !not_inheriting; + hl->h = nh; + } } +#endif /* Create a new handle record */ static handle_list * __stdcall newh () { handle_list *hl; - lock_debug (); - for (hl = freeh; hl < freeh + NFREEH; hl++) - if (hl->name == NULL) - goto out; + lock_debug here; - /* All used up??? */ - if ((hl = (handle_list *) malloc (sizeof *hl)) != NULL) - { - memset (hl, 0, sizeof (*hl)); - hl->allocated = TRUE; - } + for (hl = cygheap->debug.freeh; hl < cygheap->debug.freeh + NFREEH; hl++) + if (hl->name == NULL) + return hl; -out: - unlock_debug (); - return hl; + return NULL; } /* Add a handle to the linked list of known handles. */ void __stdcall -add_handle (const char *func, int ln, HANDLE h, const char *name) +add_handle (const char *func, int ln, HANDLE h, const char *name, bool inh) { handle_list *hl; - lock_debug (); + lock_debug here; if ((hl = find_handle (h))) { hl = hl->next; + if (hl->name == name && hl->func == func && hl->ln == ln) + return; system_printf ("%s:%d - multiple attempts to add handle %s<%p>", func, ln, name, h); - system_printf (" previously allocated by %s:%d(%s<%p>)", - hl->func, hl->ln, hl->name, hl->h); - goto out; /* Already did this once */ + system_printf (" previously allocated by %s:%d(%s<%p>) winpid %d", + hl->func, hl->ln, hl->name, hl->h, hl->pid); + return; } if ((hl = newh ()) == NULL) { - unlock_debug (); - system_printf ("couldn't allocate memory for %s(%d): %s(%p)", - func, ln, name, h); + here.unlock (); + debug_printf ("couldn't allocate memory for %s(%d): %s(%p)", + func, ln, name, h); return; } hl->h = h; @@ -271,44 +137,48 @@ add_handle (const char *func, int ln, HANDLE h, const char *name) hl->func = func; hl->ln = ln; hl->next = NULL; - endh->next = hl; - endh = hl; + hl->inherited = inh; + hl->pid = GetCurrentProcessId (); + cygheap->debug.endh->next = hl; + cygheap->debug.endh = hl; + debug_printf ("protecting handle '%s', inherited flag %d", hl->name, hl->inherited); -out: - unlock_debug (); + return; } static void __stdcall delete_handle (handle_list *hl) { handle_list *hnuke = hl->next; + debug_printf ("nuking handle '%s'", hnuke->name); hl->next = hl->next->next; - if (hnuke->allocated) - free (hnuke); - else - memset (hnuke, 0, sizeof (*hnuke)); + memset (hnuke, 0, sizeof (*hnuke)); } void -debug_fixup_after_fork () +debug_fixup_after_fork_exec () { + /* No lock needed at this point */ handle_list *hl; - for (hl = &starth; hl->next != NULL; hl = hl->next) - if (hl->next->clexec_pid) - delete_handle (hl); + for (hl = &cygheap->debug.starth; hl->next != NULL; /* nothing */) + if (hl->next->inherited) + hl = hl->next; + else + delete_handle (hl); // removes hl->next } static bool __stdcall mark_closed (const char *func, int ln, HANDLE h, const char *name, BOOL force) { handle_list *hl; - lock_debug (); + lock_debug here; + if ((hl = find_handle (h)) && !force) { hl = hl->next; - unlock_debug (); // race here - system_printf ("attempt to close protected handle %s:%d(%s<%p>)", - hl->func, hl->ln, hl->name, hl->h); + here.unlock (); // race here + system_printf ("attempt to close protected handle %s:%d(%s<%p>) winpid %d", + hl->func, hl->ln, hl->name, hl->h, hl->pid); system_printf (" by %s:%d(%s<%p>)", func, ln, name, h); return FALSE; } @@ -324,7 +194,6 @@ mark_closed (const char *func, int ln, HANDLE h, const char *name, BOOL force) if (hl) delete_handle (hl); - unlock_debug (); return TRUE; } @@ -334,18 +203,24 @@ BOOL __stdcall close_handle (const char *func, int ln, HANDLE h, const char *name, BOOL force) { BOOL ret; - lock_debug (); + lock_debug here; if (!mark_closed (func, ln, h, name, force)) return FALSE; ret = CloseHandle (h); - unlock_debug (); #if 0 /* Uncomment to see CloseHandle failures */ if (!ret) small_printf ("CloseHandle(%s) failed %s:%d\n", name, func, ln); #endif return ret; } + +int __stdcall +__set_errno (const char *func, int ln, int val) +{ + debug_printf ("%s:%d val %d", func, ln, val); + return _impure_ptr->_errno = val; +} #endif /*DEBUGGING*/ |