Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'winsup/cygwin')
-rw-r--r--winsup/cygwin/ChangeLog7
-rw-r--r--winsup/cygwin/cygtls.cc18
-rw-r--r--winsup/cygwin/dll_init.cc13
-rw-r--r--winsup/cygwin/fhandler.h17
-rw-r--r--winsup/cygwin/fhandler_fifo.cc130
5 files changed, 142 insertions, 43 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index b1684c608..71b4a4aa8 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,5 +1,12 @@
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
exception handler twice.
diff --git a/winsup/cygwin/cygtls.cc b/winsup/cygwin/cygtls.cc
index f474d9b35..b90b25fa2 100644
--- a/winsup/cygwin/cygtls.cc
+++ b/winsup/cygwin/cygtls.cc
@@ -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;
diff --git a/winsup/cygwin/dll_init.cc b/winsup/cygwin/dll_init.cc
index 6743d2601..1f83fb9a9 100644
--- a/winsup/cygwin/dll_init.cc
+++ b/winsup/cygwin/dll_init.cc
@@ -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)
diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index 465924190..ed2f6eaf3 100644
--- a/winsup/cygwin/fhandler.h
+++ b/winsup/cygwin/fhandler.h
@@ -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&);
diff --git a/winsup/cygwin/fhandler_fifo.cc b/winsup/cygwin/fhandler_fifo.cc
index 517eceb31..9ee4b9a6a 100644
--- a/winsup/cygwin/fhandler_fifo.cc
+++ b/winsup/cygwin/fhandler_fifo.cc
@@ -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