diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 1ba6827e6..f760764dc 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,16 @@ +2011-04-20 Christopher Faylor + + * cygheap.cc (init_cygheap::close_ctty): Avoid closing console-cttys + since they don't use archetypes and this will just result in double + frees. + * dll_init.cc (dll_list::protect): Define. + (dll_list::alloc): Guard list access. + (dll_list::detach): Ditto. + * dll_init.h (dll_list::protect): Declare new muto. + (dll_list::guard): Define/declare function to guard list access. + * fhandler_termios.cc (fhandler_termios::sigflush): Avoid SEGV in + pathological condition of get_ttyp() == NULL. + 2011-04-20 Christopher Faylor * select.cc (serial_cleanup): Make sure that device_specific_pipe is diff --git a/winsup/cygwin/cygheap.cc b/winsup/cygwin/cygheap.cc index 00e9796f6..8dde3dfe9 100644 --- a/winsup/cygwin/cygheap.cc +++ b/winsup/cygwin/cygheap.cc @@ -15,6 +15,7 @@ #include "cygerrno.h" #include "security.h" #include "path.h" +#include "tty.h" #include "fhandler.h" #include "dtable.h" #include "cygheap.h" @@ -106,7 +107,11 @@ void init_cygheap::close_ctty () { debug_printf ("closing cygheap->ctty %p", cygheap->ctty); - cygheap->ctty->close (); + /* FIXME: Support for console-as-ctty is limited due to the fact that + the console doesn't use archetypes - even though they could and should */ + if (cygheap->ctty->get_ttyp () + && cygheap->ctty->get_ttyp ()->ntty != TTY_CONSOLE) + cygheap->ctty->close (); cygheap->ctty = NULL; } diff --git a/winsup/cygwin/dll_init.cc b/winsup/cygwin/dll_init.cc index 5ee2f0036..f457b2766 100644 --- a/winsup/cygwin/dll_init.cc +++ b/winsup/cygwin/dll_init.cc @@ -10,6 +10,7 @@ details. */ #include "winsup.h" #include "cygerrno.h" #include "perprocess.h" +#include "sync.h" #include "dll_init.h" #include "environ.h" #include "security.h" @@ -28,6 +29,8 @@ extern void __stdcall check_sanity_and_sync (per_process *); dll_list dlls; +muto dll_list::protect; + static bool dll_global_dtors_recorded; /* Run destructors for all DLLs on exit. */ @@ -116,6 +119,7 @@ dll_list::alloc (HINSTANCE h, per_process *p, dll_type type) WCHAR name[NT_MAX_PATH]; DWORD namelen = GetModuleFileNameW (h, name, sizeof (name)); + guard (true); /* Already loaded? */ dll *d = dlls[name]; if (d) @@ -146,6 +150,7 @@ dll_list::alloc (HINSTANCE h, per_process *p, dll_type type) if (type == DLL_LOAD) loaded_dlls++; } + guard (false); assert (p->envptr != NULL); return d; } @@ -170,27 +175,32 @@ void dll_list::detach (void *retaddr) { dll *d; - if (!myself || !(d = find (retaddr))) + if (!myself) return; - if (d->count <= 0) - system_printf ("WARNING: trying to detach an already detached dll ..."); - if (--d->count == 0) + guard (true); + if ((d = find (retaddr))) { - /* Ensure our exception handler is enabled for destructors */ - exception protect; - /* Call finalize function if we are not already exiting */ - if (!exit_state) - __cxa_finalize (d); - d->run_dtors (); - d->prev->next = d->next; - if (d->next) - d->next->prev = d->prev; - if (d->type == DLL_LOAD) - loaded_dlls--; - if (end == d) - end = d->prev; - cfree (d); + if (d->count <= 0) + system_printf ("WARNING: trying to detach an already detached dll ..."); + if (--d->count == 0) + { + /* Ensure our exception handler is enabled for destructors */ + exception protect; + /* Call finalize function if we are not already exiting */ + if (!exit_state) + __cxa_finalize (d); + d->run_dtors (); + d->prev->next = d->next; + if (d->next) + d->next->prev = d->prev; + if (d->type == DLL_LOAD) + loaded_dlls--; + if (end == d) + end = d->prev; + cfree (d); + } } + guard (false); } /* Initialization for all linked DLLs, called by dll_crt0_1. */ diff --git a/winsup/cygwin/dll_init.h b/winsup/cygwin/dll_init.h index b37406e82..d14cc6cb9 100644 --- a/winsup/cygwin/dll_init.h +++ b/winsup/cygwin/dll_init.h @@ -72,6 +72,7 @@ class dll_list dll *end; dll *hold; dll_type hold_type; + static muto protect; public: dll start; int tot; @@ -90,13 +91,22 @@ public: break; return hold; } + dll *istart (dll_type t) { hold_type = t; hold = &start; return inext (); } + void guard(bool lockit) + { + if (lockit) + protect.acquire (); + else + protect.release (); + } friend void dll_global_dtors (); + dll_list () { protect.init ("dll_list"); } }; extern dll_list dlls; diff --git a/winsup/cygwin/fhandler_termios.cc b/winsup/cygwin/fhandler_termios.cc index bdfce4642..80131a796 100644 --- a/winsup/cygwin/fhandler_termios.cc +++ b/winsup/cygwin/fhandler_termios.cc @@ -371,6 +371,9 @@ fhandler_termios::lseek (_off64_t, int) void fhandler_termios::sigflush () { - if (!(get_ttyp ()->ti.c_lflag & NOFLSH)) + /* FIXME: Checking get_ttyp() for NULL is not right since it should not + be NULL while this is alive. However, we can conceivably close a + ctty while exiting and that will zero this. */ + if (get_ttyp () && !(get_ttyp ()->ti.c_lflag & NOFLSH)) tcflush (TCIFLUSH); } diff --git a/winsup/cygwin/sync.cc b/winsup/cygwin/sync.cc index b62c6bcb7..58b854912 100644 --- a/winsup/cygwin/sync.cc +++ b/winsup/cygwin/sync.cc @@ -4,7 +4,7 @@ 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 Red Hat, Inc. + Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009, 2010 Red Hat, Inc. This file is part of Cygwin.