* 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>
* cygtls.cc (_cygtls::init_exception_handler): Avoid adding our

View File

@ -228,7 +228,23 @@ extern exception_list *_except_list asm ("%fs:0");
void
_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)
return;
el.handler = eh;

View File

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

View File

@ -572,19 +572,22 @@ public:
friend class fhandler_fifo;
};
enum fifo_state
{
fifo_unknown,
fifo_wait_for_client,
fifo_wait_for_server,
fifo_ok
};
class fhandler_fifo: public fhandler_base
{
enum fifo_state
{
fifo_unknown,
fifo_wait_for_client,
fifo_wait_for_server,
fifo_wait_for_next_client,
fifo_eof,
fifo_ok
};
fifo_state wait_state;
HANDLE open_nonserver (const char *, unsigned, LPSECURITY_ATTRIBUTES);
OVERLAPPED io_status;
bool wait (bool) __attribute__ ((regparm (1)));
char *fifo_name (char *) __attribute__ ((regparm (2)));
public:
fhandler_fifo ();
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)
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
fhandler_fifo::open (int flags, mode_t)
{
int res;
int res = 1;
char npname[MAX_PATH];
DWORD mode = 0;
/* Generate a semi-unique name to associate with this fifo. */
__small_sprintf (npname, "\\\\.\\pipe\\__cygfifo__%08x_%016X",
get_dev (), get_ino ());
fifo_name (npname);
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;
else if (low_flags == O_WRONLY)
mode = PIPE_ACCESS_OUTBOUND;
else if (low_flags == O_RDWR)
mode = PIPE_ACCESS_DUPLEX;
if (!mode)
else
{
set_errno (EINVAL);
res = 0;
}
else
if (res)
{
char char_sa_buf[1024];
LPSECURITY_ATTRIBUTES sa_buf =
@ -90,7 +97,7 @@ fhandler_fifo::open (int flags, mode_t)
HANDLE h;
DWORD err;
bool nonblocking_write = !!((flags & (O_WRONLY | O_NONBLOCK)) == (O_WRONLY | O_NONBLOCK));
if (nonblocking_write)
if (flags & O_WRONLY)
{
h = INVALID_HANDLE_VALUE;
err = ERROR_ACCESS_DENIED;
@ -111,20 +118,25 @@ fhandler_fifo::open (int flags, mode_t)
h = open_nonserver (npname, low_flags, sa_buf);
if (h != INVALID_HANDLE_VALUE)
{
wait_state = fifo_wait_for_server;
wait_state = fifo_ok;
break;
}
if (nonblocking_write && GetLastError () == ERROR_FILE_NOT_FOUND)
if (GetLastError () != ERROR_FILE_NOT_FOUND)
__seterrno ();
else if (nonblocking_write)
set_errno (ENXIO);
else
{
set_errno (ENXIO);
break;
h = NULL;
nohandle (true);
wait_state = fifo_wait_for_server;
}
/* fall through intentionally */
break;
default:
__seterrno ();
break;
}
if (!h || h == INVALID_HANDLE_VALUE)
if (h == INVALID_HANDLE_VALUE)
res = 0;
else if (!setup_overlapped ())
{
@ -148,17 +160,72 @@ fhandler_fifo::wait (bool iswrite)
{
switch (wait_state)
{
case fifo_wait_for_next_client:
DisconnectNamedPipe (get_handle ());
case fifo_wait_for_client:
{
bool res = ConnectNamedPipe (get_handle (), get_overlapped ());
DWORD dummy_bytes;
if (res || GetLastError () == ERROR_PIPE_CONNECTED)
return true;
return wait_overlapped (res, iswrite, &dummy_bytes);
int res;
if ((res = ConnectNamedPipe (get_handle (), get_overlapped ()))
|| GetLastError () == ERROR_PIPE_CONNECTED)
{
wait_state = fifo_ok;
return true;
}
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;
}
case fifo_unknown:
break;
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:
break;
}
@ -168,10 +235,15 @@ fhandler_fifo::wait (bool iswrite)
void
fhandler_fifo::raw_read (void *in_ptr, size_t& len)
{
if (!wait (false))
len = 0;
else
read_overlapped (in_ptr, len);
while (wait_state != fifo_eof)
if (!wait (false))
len = 0;
else
{
read_overlapped (in_ptr, len);
if (!len)
wait_state = fifo_wait_for_next_client;
}
}
int