diff options
Diffstat (limited to 'winsup/cygwin/fhandler_windows.cc')
-rw-r--r-- | winsup/cygwin/fhandler_windows.cc | 66 |
1 files changed, 54 insertions, 12 deletions
diff --git a/winsup/cygwin/fhandler_windows.cc b/winsup/cygwin/fhandler_windows.cc index 7475b89bb..119266093 100644 --- a/winsup/cygwin/fhandler_windows.cc +++ b/winsup/cygwin/fhandler_windows.cc @@ -1,7 +1,7 @@ /* fhandler_windows.cc: code to access windows message queues. - Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2009 - Red Hat, Inc. + Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2009, + 2011 Red Hat, Inc. Written by Sergey S. Okhapkin (sos@prospect.com.ru). Feedback and testing by Andy Piper (andyp@parallax.co.uk). @@ -18,13 +18,15 @@ details. */ #include "cygerrno.h" #include "path.h" #include "fhandler.h" +#include "sigproc.h" +#include "thread.h" + /* The following unix-style calls are supported: open ("/dev/windows", flags, mode=0) - create a unix fd for message queue. - O_NONBLOCK flag controls the read() call behavior. read (fd, buf, len) - return next message from queue. buf must point to MSG @@ -67,16 +69,19 @@ fhandler_windows::write (const void *buf, size_t) if (method_ == WINDOWS_POST) { - if (!PostMessage (ptr->hwnd, ptr->message, ptr->wParam, ptr->lParam)) + if (!PostMessageW (ptr->hwnd, ptr->message, ptr->wParam, ptr->lParam)) { __seterrno (); return -1; } - else - return sizeof (MSG); } - else - return SendMessage (ptr->hwnd, ptr->message, ptr->wParam, ptr->lParam); + else if (!SendNotifyMessageW (ptr->hwnd, ptr->message, ptr->wParam, + ptr->lParam)) + { + __seterrno (); + return -1; + } + return sizeof (MSG); } void __stdcall @@ -91,10 +96,47 @@ fhandler_windows::read (void *buf, size_t& len) return; } - len = (size_t) GetMessage (ptr, hWnd_, 0, 0); - - if ((ssize_t) len == -1) - __seterrno (); + HANDLE w4[3] = { get_handle (), signal_arrived, NULL }; + DWORD cnt = 2; + pthread_t thread = pthread::self (); + if (thread && thread->cancel_event + && thread->cancelstate != PTHREAD_CANCEL_DISABLE) + w4[cnt++] = thread->cancel_event; +restart: + switch (MsgWaitForMultipleObjectsEx (cnt, w4, + is_nonblocking () ? 0 : INFINITE, + QS_ALLINPUT | QS_ALLPOSTMESSAGE, + MWMO_INPUTAVAILABLE)) + { + case WAIT_OBJECT_0: + if (!PeekMessageW (ptr, hWnd_, 0, 0, PM_REMOVE)) + { + len = (size_t) -1; + __seterrno (); + } + else if (ptr->message == WM_QUIT) + len = 0; + else + len = sizeof (MSG); + break; + case WAIT_OBJECT_0 + 1: + if (_my_tls.call_signal_handler ()) + goto restart; + len = (size_t) -1; + set_errno (EINTR); + break; + case WAIT_OBJECT_0 + 2: + pthread::static_cancel_self (); + break; + case WAIT_TIMEOUT: + len = (size_t) -1; + set_errno (EAGAIN); + break; + default: + len = (size_t) -1; + __seterrno (); + break; + } } int |