* cygtls.cc (_cygtls::init_exception_handler): Test for e, not e->prev or we

could still end up adding our handler twice.  Add comment explaining what we're
doing.
* dll_init.cc (dll_dllcrt0_1): Clarify comment.
This commit is contained in:
Christopher Faylor 2009-07-17 18:17:11 +00:00
parent d2445fa2cc
commit 486a2c9610
5 changed files with 142 additions and 43 deletions

View File

@ -1,3 +1,10 @@
2009-07-17 Christopher Faylor <me+cygwin@cgf.cx>
* cygtls.cc (_cygtls::init_exception_handler): Test for e, not e->prev
or we could still end up adding our handler twice. Add comment
explaining what we're doing.
* dll_init.cc (dll_dllcrt0_1): Clarify comment.
2009-07-17 Christopher Faylor <me+cygwin@cgf.cx> 2009-07-17 Christopher Faylor <me+cygwin@cgf.cx>
* cygtls.cc (_cygtls::init_exception_handler): Avoid adding our * cygtls.cc (_cygtls::init_exception_handler): Avoid adding our

View File

@ -228,7 +228,23 @@ extern exception_list *_except_list asm ("%fs:0");
void void
_cygtls::init_exception_handler (exception_handler *eh) _cygtls::init_exception_handler (exception_handler *eh)
{ {
for (exception_list *e = _except_list; e->prev != NULL && e->prev != (exception_list *)-1; e = e->prev) /* Here in the distant past of 17-Jul-2009, we had an issue where Windows
2008 became YA perplexed because the cygwin exception handler was added
at the start of the SEH while still being in the list further on. This
was because we added a loop by setting el.prev to _except_list here.
Since el is reused in this thread, and this function can be called
more than once when a dll is loaded, this is not a good thing.
So, for now, until the next required tweak, we will just avoid adding the
cygwin exception handler if it is already on this list. This could present
a problem if some previous exception handler tries to do things that are
better left to Cygwin. I await the cygwin mailing list notification of
this event with bated breath.
(cgf 2009-07-17) */
for (exception_list *e = _except_list;
e != NULL && e != (exception_list *) -1;
e = e->prev)
if (e == &el) if (e == &el)
return; return;
el.handler = eh; el.handler = eh;

View File

@ -312,12 +312,13 @@ dll_dllcrt0_1 (VOID *x)
per_process*& p = ((dllcrt0_info *)x)->p; per_process*& p = ((dllcrt0_info *)x)->p;
int& res = ((dllcrt0_info *)x)->res; int& res = ((dllcrt0_info *)x)->res;
/* Windows apparently installs a bunch of exception handlers prior to /* Make sure that our exception handler is installed.
this function getting called and one of them may trip before cygwin That should always be the case but this just makes sure.
gets to it. So, install our own exception handler only.
FIXME: It is possible that we may have to save state of the At some point, we may want to just remove this code since
previous exception handler chain and restore it, if problems the exception handler should be guaranteed to be installed.
are noted. */ I'm leaving it in until potentially after the release of
1.7.1 */
_my_tls.init_exception_handler (_cygtls::handle_exceptions); _my_tls.init_exception_handler (_cygtls::handle_exceptions);
if (p == NULL) if (p == NULL)

View File

@ -572,19 +572,22 @@ public:
friend class fhandler_fifo; friend class fhandler_fifo;
}; };
enum fifo_state class fhandler_fifo: public fhandler_base
{ {
enum fifo_state
{
fifo_unknown, fifo_unknown,
fifo_wait_for_client, fifo_wait_for_client,
fifo_wait_for_server, fifo_wait_for_server,
fifo_wait_for_next_client,
fifo_eof,
fifo_ok fifo_ok
}; };
class fhandler_fifo: public fhandler_base
{
fifo_state wait_state; fifo_state wait_state;
HANDLE open_nonserver (const char *, unsigned, LPSECURITY_ATTRIBUTES); HANDLE open_nonserver (const char *, unsigned, LPSECURITY_ATTRIBUTES);
OVERLAPPED io_status; OVERLAPPED io_status;
bool wait (bool) __attribute__ ((regparm (1))); bool wait (bool) __attribute__ ((regparm (1)));
char *fifo_name (char *) __attribute__ ((regparm (2)));
public: public:
fhandler_fifo (); fhandler_fifo ();
void raw_read (void *, size_t&); void raw_read (void *, size_t&);

View File

@ -56,31 +56,38 @@ fhandler_fifo::open_nonserver (const char *npname, unsigned low_flags,
#define FIFO_PIPE_MODE (PIPE_TYPE_BYTE | PIPE_READMODE_BYTE) #define FIFO_PIPE_MODE (PIPE_TYPE_BYTE | PIPE_READMODE_BYTE)
char *
fhandler_fifo::fifo_name (char *buf)
{
/* Generate a semi-unique name to associate with this fifo. */
__small_sprintf (buf, "\\\\.\\pipe\\__cygfifo__%08x_%016X",
get_dev (), get_ino ());
return buf;
}
int int
fhandler_fifo::open (int flags, mode_t) fhandler_fifo::open (int flags, mode_t)
{ {
int res; int res = 1;
char npname[MAX_PATH]; char npname[MAX_PATH];
DWORD mode = 0;
/* Generate a semi-unique name to associate with this fifo. */ fifo_name (npname);
__small_sprintf (npname, "\\\\.\\pipe\\__cygfifo__%08x_%016X",
get_dev (), get_ino ());
unsigned low_flags = flags & O_ACCMODE; unsigned low_flags = flags & O_ACCMODE;
if (low_flags == O_RDONLY) DWORD mode = 0;
if (low_flags == O_WRONLY)
/* ok */;
else if (low_flags == O_RDONLY)
mode = PIPE_ACCESS_INBOUND; mode = PIPE_ACCESS_INBOUND;
else if (low_flags == O_WRONLY)
mode = PIPE_ACCESS_OUTBOUND;
else if (low_flags == O_RDWR) else if (low_flags == O_RDWR)
mode = PIPE_ACCESS_DUPLEX; mode = PIPE_ACCESS_DUPLEX;
else
if (!mode)
{ {
set_errno (EINVAL); set_errno (EINVAL);
res = 0; res = 0;
} }
else
if (res)
{ {
char char_sa_buf[1024]; char char_sa_buf[1024];
LPSECURITY_ATTRIBUTES sa_buf = LPSECURITY_ATTRIBUTES sa_buf =
@ -90,7 +97,7 @@ fhandler_fifo::open (int flags, mode_t)
HANDLE h; HANDLE h;
DWORD err; DWORD err;
bool nonblocking_write = !!((flags & (O_WRONLY | O_NONBLOCK)) == (O_WRONLY | O_NONBLOCK)); bool nonblocking_write = !!((flags & (O_WRONLY | O_NONBLOCK)) == (O_WRONLY | O_NONBLOCK));
if (nonblocking_write) if (flags & O_WRONLY)
{ {
h = INVALID_HANDLE_VALUE; h = INVALID_HANDLE_VALUE;
err = ERROR_ACCESS_DENIED; err = ERROR_ACCESS_DENIED;
@ -111,20 +118,25 @@ fhandler_fifo::open (int flags, mode_t)
h = open_nonserver (npname, low_flags, sa_buf); h = open_nonserver (npname, low_flags, sa_buf);
if (h != INVALID_HANDLE_VALUE) if (h != INVALID_HANDLE_VALUE)
{ {
wait_state = fifo_wait_for_server; wait_state = fifo_ok;
break; break;
} }
if (nonblocking_write && GetLastError () == ERROR_FILE_NOT_FOUND) if (GetLastError () != ERROR_FILE_NOT_FOUND)
{ __seterrno ();
else if (nonblocking_write)
set_errno (ENXIO); set_errno (ENXIO);
break; else
{
h = NULL;
nohandle (true);
wait_state = fifo_wait_for_server;
} }
/* fall through intentionally */ break;
default: default:
__seterrno (); __seterrno ();
break; break;
} }
if (!h || h == INVALID_HANDLE_VALUE) if (h == INVALID_HANDLE_VALUE)
res = 0; res = 0;
else if (!setup_overlapped ()) else if (!setup_overlapped ())
{ {
@ -148,17 +160,72 @@ fhandler_fifo::wait (bool iswrite)
{ {
switch (wait_state) switch (wait_state)
{ {
case fifo_wait_for_next_client:
DisconnectNamedPipe (get_handle ());
case fifo_wait_for_client: case fifo_wait_for_client:
{ {
bool res = ConnectNamedPipe (get_handle (), get_overlapped ()); int res;
DWORD dummy_bytes; if ((res = ConnectNamedPipe (get_handle (), get_overlapped ()))
if (res || GetLastError () == ERROR_PIPE_CONNECTED) || GetLastError () == ERROR_PIPE_CONNECTED)
{
wait_state = fifo_ok;
return true; return true;
return wait_overlapped (res, iswrite, &dummy_bytes);
} }
case fifo_unknown: if (wait_state == fifo_wait_for_next_client)
{
CancelIo (get_handle ());
res = 0;
}
else
{
DWORD dummy_bytes;
res = wait_overlapped (res, iswrite, &dummy_bytes);
}
wait_state = res ? fifo_ok : fifo_eof;
}
break;
case fifo_wait_for_server: case fifo_wait_for_server:
/* CGF FIXME SOON: test if these really need to be handled. */ if (get_io_handle ())
break;
char npname[MAX_PATH];
fifo_name (npname);
char char_sa_buf[1024];
LPSECURITY_ATTRIBUTES sa_buf;
sa_buf = sec_user ((PSECURITY_ATTRIBUTES) char_sa_buf, cygheap->user.sid());
while (1)
{
if (WaitNamedPipe (npname, 10))
/* connected, maybe */;
else if (GetLastError () != ERROR_SEM_TIMEOUT)
{
__seterrno ();
return false;
}
else if (WaitForSingleObject (signal_arrived, 0) != WAIT_OBJECT_0)
continue;
else if (_my_tls.call_signal_handler ())
continue;
else
{
set_errno (EINTR);
return false;
}
HANDLE h = open_nonserver (npname, get_flags () & O_ACCMODE, sa_buf);
if (h != INVALID_HANDLE_VALUE)
{
wait_state = fifo_ok;
set_io_handle (h);
nohandle (false);
break;
}
if (GetLastError () == ERROR_PIPE_LISTENING)
continue;
else
{
__seterrno ();
return false;
}
}
default: default:
break; break;
} }
@ -168,10 +235,15 @@ fhandler_fifo::wait (bool iswrite)
void void
fhandler_fifo::raw_read (void *in_ptr, size_t& len) fhandler_fifo::raw_read (void *in_ptr, size_t& len)
{ {
while (wait_state != fifo_eof)
if (!wait (false)) if (!wait (false))
len = 0; len = 0;
else else
{
read_overlapped (in_ptr, len); read_overlapped (in_ptr, len);
if (!len)
wait_state = fifo_wait_for_next_client;
}
} }
int int