X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=glib%2Fgiowin32.c;h=171fb6803bffb4a5f1000b1f39fbdfb731759e48;hb=20f6cc2a10ba26860e7a6d27c100deadb5497772;hp=711f5cf88e43fafea5f25563a5282ca4390f3f05;hpb=5becc45bf4294efb2b11cfca82eb2fe82dcb7895;p=platform%2Fupstream%2Fglib.git diff --git a/glib/giowin32.c b/glib/giowin32.c index 711f5cf..171fb68 100644 --- a/glib/giowin32.c +++ b/glib/giowin32.c @@ -17,9 +17,7 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * License along with this library; if not, see . */ /* @@ -84,7 +82,6 @@ #include "gstdio.h" #include "glibintl.h" -#include "galias.h" typedef struct _GIOWin32Channel GIOWin32Channel; typedef struct _GIOWin32Watch GIOWin32Watch; @@ -163,9 +160,6 @@ struct _GIOWin32Channel { gboolean ever_writable; }; -#define LOCK(mutex) EnterCriticalSection (&mutex) -#define UNLOCK(mutex) LeaveCriticalSection (&mutex) - struct _GIOWin32Watch { GSource source; GPollFD pollfd; @@ -202,8 +196,8 @@ g_win32_print_gioflags (GIOFlags flags) g_print ("%sNONBLOCK", bar), bar = "|"; if (flags & G_IO_FLAG_IS_READABLE) g_print ("%sREADABLE", bar), bar = "|"; - if (flags & G_IO_FLAG_IS_WRITEABLE) - g_print ("%sWRITEABLE", bar), bar = "|"; + if (flags & G_IO_FLAG_IS_WRITABLE) + g_print ("%sWRITABLE", bar), bar = "|"; if (flags & G_IO_FLAG_IS_SEEKABLE) g_print ("%sSEEKABLE", bar), bar = "|"; } @@ -276,19 +270,21 @@ static void g_io_channel_win32_init (GIOWin32Channel *channel) { channel->debug = g_io_win32_get_debug_flag (); - channel->buffer = NULL; + + InitializeCriticalSection (&channel->mutex); channel->running = FALSE; channel->needs_close = FALSE; channel->thread_id = 0; channel->data_avail_event = NULL; channel->revents = 0; + channel->buffer = NULL; channel->space_avail_event = NULL; + channel->event_mask = 0; channel->last_events = 0; channel->event = NULL; channel->write_would_have_blocked = FALSE; channel->ever_writable = FALSE; - InitializeCriticalSection (&channel->mutex); } static void @@ -307,6 +303,7 @@ create_events (GIOWin32Channel *channel) || !(channel->space_avail_event = CreateEvent (&sec_attrs, FALSE, FALSE, NULL))) { gchar *emsg = g_win32_error_message (GetLastError ()); + g_error ("Error creating event: %s", emsg); g_free (emsg); } @@ -335,7 +332,7 @@ read_thread (void *parameter) SetEvent (channel->space_avail_event); - LOCK (channel->mutex); + EnterCriticalSection (&channel->mutex); while (channel->running) { if (channel->debug) @@ -351,9 +348,9 @@ read_thread (void *parameter) if (channel->debug) g_print ("read_thread %#x: waiting for space\n", channel->thread_id); - UNLOCK (channel->mutex); + LeaveCriticalSection (&channel->mutex); WaitForSingleObject (channel->space_avail_event, INFINITE); - LOCK (channel->mutex); + EnterCriticalSection (&channel->mutex); if (channel->debug) g_print ("read_thread %#x: rdp=%d, wrp=%d\n", channel->thread_id, channel->rdp, channel->wrp); @@ -371,11 +368,11 @@ read_thread (void *parameter) g_print ("read_thread %#x: calling read() for %d bytes\n", channel->thread_id, nbytes); - UNLOCK (channel->mutex); + LeaveCriticalSection (&channel->mutex); nbytes = read (channel->fd, buffer, nbytes); - LOCK (channel->mutex); + EnterCriticalSection (&channel->mutex); channel->revents = G_IO_IN; if (nbytes == 0) @@ -411,7 +408,7 @@ read_thread (void *parameter) g_print ("read_thread %#x: EOF, rdp=%d, wrp=%d, setting data_avail\n", channel->thread_id, channel->rdp, channel->wrp); SetEvent (channel->data_avail_event); - UNLOCK (channel->mutex); + LeaveCriticalSection (&channel->mutex); g_io_channel_unref ((GIOChannel *)channel); @@ -452,7 +449,7 @@ write_thread (void *parameter) * write buffer. */ - LOCK (channel->mutex); + EnterCriticalSection (&channel->mutex); while (channel->running || channel->rdp != channel->wrp) { if (channel->debug) @@ -470,10 +467,10 @@ write_thread (void *parameter) channel->thread_id); channel->revents = G_IO_OUT; SetEvent (channel->data_avail_event); - UNLOCK (channel->mutex); + LeaveCriticalSection (&channel->mutex); WaitForSingleObject (channel->space_avail_event, INFINITE); - LOCK (channel->mutex); + EnterCriticalSection (&channel->mutex); if (channel->rdp == channel->wrp) break; @@ -492,9 +489,9 @@ write_thread (void *parameter) g_print ("write_thread %#x: calling write() for %d bytes\n", channel->thread_id, nbytes); - UNLOCK (channel->mutex); + LeaveCriticalSection (&channel->mutex); nbytes = write (channel->fd, buffer, nbytes); - LOCK (channel->mutex); + EnterCriticalSection (&channel->mutex); if (channel->debug) g_print ("write_thread %#x: write(%i) returned %d, rdp=%d, wrp=%d\n", @@ -527,7 +524,7 @@ write_thread (void *parameter) channel->fd = -1; } - UNLOCK (channel->mutex); + LeaveCriticalSection (&channel->mutex); g_io_channel_unref ((GIOChannel *)channel); @@ -547,8 +544,12 @@ create_thread (GIOWin32Channel *channel, g_warning ("Error creating thread: %s.", g_strerror (errno)); else if (!CloseHandle (thread_handle)) - g_warning ("Error closing thread handle: %s.\n", - g_win32_error_message (GetLastError ())); + { + gchar *emsg = g_win32_error_message (GetLastError ()); + + g_warning ("Error closing thread handle: %s.", emsg); + g_free (emsg); + } WaitForSingleObject (channel->space_avail_event, INFINITE); } @@ -563,25 +564,25 @@ buffer_read (GIOWin32Channel *channel, guint nbytes; guint left = count; - LOCK (channel->mutex); + EnterCriticalSection (&channel->mutex); if (channel->debug) g_print ("reading from thread %#x %" G_GSIZE_FORMAT " bytes, rdp=%d, wrp=%d\n", channel->thread_id, count, channel->rdp, channel->wrp); if (channel->wrp == channel->rdp) { - UNLOCK (channel->mutex); + LeaveCriticalSection (&channel->mutex); if (channel->debug) g_print ("waiting for data from thread %#x\n", channel->thread_id); WaitForSingleObject (channel->data_avail_event, INFINITE); if (channel->debug) g_print ("done waiting for data from thread %#x\n", channel->thread_id); - LOCK (channel->mutex); + EnterCriticalSection (&channel->mutex); if (channel->wrp == channel->rdp && !channel->running) { if (channel->debug) g_print ("wrp==rdp, !running\n"); - UNLOCK (channel->mutex); + LeaveCriticalSection (&channel->mutex); *bytes_read = 0; return G_IO_STATUS_EOF; } @@ -591,7 +592,7 @@ buffer_read (GIOWin32Channel *channel, nbytes = channel->wrp - channel->rdp; else nbytes = BUFFER_SIZE - channel->rdp; - UNLOCK (channel->mutex); + LeaveCriticalSection (&channel->mutex); nbytes = MIN (left, nbytes); if (channel->debug) g_print ("moving %d bytes from thread %#x\n", @@ -599,7 +600,7 @@ buffer_read (GIOWin32Channel *channel, memcpy (dest, channel->buffer + channel->rdp, nbytes); dest += nbytes; left -= nbytes; - LOCK (channel->mutex); + EnterCriticalSection (&channel->mutex); channel->rdp = (channel->rdp + nbytes) % BUFFER_SIZE; if (channel->debug) g_print ("setting space_avail for thread %#x\n", channel->thread_id); @@ -614,7 +615,7 @@ buffer_read (GIOWin32Channel *channel, channel->thread_id); ResetEvent (channel->data_avail_event); }; - UNLOCK (channel->mutex); + LeaveCriticalSection (&channel->mutex); /* We have no way to indicate any errors form the actual * read() or recv() call in the reader thread. Should we have? @@ -634,7 +635,7 @@ buffer_write (GIOWin32Channel *channel, guint nbytes; guint left = count; - LOCK (channel->mutex); + EnterCriticalSection (&channel->mutex); if (channel->debug) g_print ("buffer_write: writing to thread %#x %" G_GSIZE_FORMAT " bytes, rdp=%d, wrp=%d\n", channel->thread_id, count, channel->rdp, channel->wrp); @@ -649,9 +650,9 @@ buffer_write (GIOWin32Channel *channel, if (channel->debug) g_print ("buffer_write: tid %#x: waiting for space\n", channel->thread_id); - UNLOCK (channel->mutex); + LeaveCriticalSection (&channel->mutex); WaitForSingleObject (channel->data_avail_event, INFINITE); - LOCK (channel->mutex); + EnterCriticalSection (&channel->mutex); if (channel->debug) g_print ("buffer_write: tid %#x: rdp=%d, wrp=%d\n", channel->thread_id, channel->rdp, channel->wrp); @@ -660,7 +661,7 @@ buffer_write (GIOWin32Channel *channel, nbytes = MIN ((channel->rdp + BUFFER_SIZE - channel->wrp - 1) % BUFFER_SIZE, BUFFER_SIZE - channel->wrp); - UNLOCK (channel->mutex); + LeaveCriticalSection (&channel->mutex); nbytes = MIN (left, nbytes); if (channel->debug) g_print ("buffer_write: tid %#x: writing %d bytes\n", @@ -668,7 +669,7 @@ buffer_write (GIOWin32Channel *channel, memcpy (channel->buffer + channel->wrp, dest, nbytes); dest += nbytes; left -= nbytes; - LOCK (channel->mutex); + EnterCriticalSection (&channel->mutex); channel->wrp = (channel->wrp + nbytes) % BUFFER_SIZE; if (channel->debug) @@ -685,7 +686,7 @@ buffer_write (GIOWin32Channel *channel, ResetEvent (channel->data_avail_event); } - UNLOCK (channel->mutex); + LeaveCriticalSection (&channel->mutex); /* We have no way to indicate any errors form the actual * write() call in the writer thread. Should we have? @@ -730,7 +731,7 @@ g_io_win32_prepare (GSource *source, condition_to_string (watch->pollfd.revents), condition_to_string (channel->revents)); - LOCK (channel->mutex); + EnterCriticalSection (&channel->mutex); if (channel->running) { if (channel->direction == 0 && channel->wrp == channel->rdp) @@ -750,7 +751,7 @@ g_io_win32_prepare (GSource *source, channel->revents = 0; } } - UNLOCK (channel->mutex); + LeaveCriticalSection (&channel->mutex); break; case G_IO_WIN32_SOCKET: @@ -771,11 +772,15 @@ g_io_win32_prepare (GSource *source, event_mask_to_string (event_mask)); if (WSAEventSelect (channel->fd, (HANDLE) watch->pollfd.fd, event_mask) == SOCKET_ERROR) - ; /* What? */ + if (channel->debug) + { + gchar *emsg = g_win32_error_message (WSAGetLastError ()); + + g_print (" failed: %s", emsg); + g_free (emsg); + } channel->event_mask = event_mask; -#if 0 - channel->event = watch->pollfd.fd; -#endif + if (channel->debug) g_print ("\n setting last_events=0"); channel->last_events = 0; @@ -1070,8 +1075,10 @@ g_io_win32_msg_write (GIOChannel *channel, if (!PostMessage (win32_channel->hwnd, msg.message, msg.wParam, msg.lParam)) { gchar *emsg = g_win32_error_message (GetLastError ()); + g_set_error_literal (err, G_IO_CHANNEL_ERROR, G_IO_CHANNEL_ERROR_FAILED, emsg); g_free (emsg); + return G_IO_STATUS_ERROR; } @@ -1097,15 +1104,55 @@ g_io_win32_free (GIOChannel *channel) if (win32_channel->debug) g_print ("g_io_win32_free channel=%p fd=%d\n", channel, win32_channel->fd); - if (win32_channel->data_avail_event) - CloseHandle (win32_channel->data_avail_event); - if (win32_channel->space_avail_event) - CloseHandle (win32_channel->space_avail_event); - if (win32_channel->type == G_IO_WIN32_SOCKET) - WSAEventSelect (win32_channel->fd, NULL, 0); DeleteCriticalSection (&win32_channel->mutex); + if (win32_channel->data_avail_event) + if (!CloseHandle (win32_channel->data_avail_event)) + if (win32_channel->debug) + { + gchar *emsg = g_win32_error_message (GetLastError ()); + + g_print (" CloseHandle(%p) failed: %s\n", + win32_channel->data_avail_event, emsg); + g_free (emsg); + } + g_free (win32_channel->buffer); + + if (win32_channel->space_avail_event) + if (!CloseHandle (win32_channel->space_avail_event)) + if (win32_channel->debug) + { + gchar *emsg = g_win32_error_message (GetLastError ()); + + g_print (" CloseHandle(%p) failed: %s\n", + win32_channel->space_avail_event, emsg); + g_free (emsg); + } + + if (win32_channel->type == G_IO_WIN32_SOCKET && + win32_channel->fd != -1) + if (WSAEventSelect (win32_channel->fd, NULL, 0) == SOCKET_ERROR) + if (win32_channel->debug) + { + gchar *emsg = g_win32_error_message (WSAGetLastError ()); + + g_print (" WSAEventSelect(%d,NULL,{}) failed: %s\n", + win32_channel->fd, emsg); + g_free (emsg); + } + + if (win32_channel->event) + if (!WSACloseEvent (win32_channel->event)) + if (win32_channel->debug) + { + gchar *emsg = g_win32_error_message (WSAGetLastError ()); + + g_print (" WSACloseEvent(%p) failed: %s\n", + win32_channel->event, emsg); + g_free (emsg); + } + g_free (win32_channel); } @@ -1117,6 +1164,7 @@ g_io_win32_msg_create_watch (GIOChannel *channel, GSource *source; source = g_source_new (&g_io_watch_funcs, sizeof (GIOWin32Watch)); + g_source_set_name (source, "GIOChannel (Win32)"); watch = (GIOWin32Watch *)source; watch->channel = channel; @@ -1282,7 +1330,7 @@ g_io_win32_fd_close (GIOChannel *channel, g_print ("g_io_win32_fd_close: thread=%#x: fd=%d\n", win32_channel->thread_id, win32_channel->fd); - LOCK (win32_channel->mutex); + EnterCriticalSection (&win32_channel->mutex); if (win32_channel->running) { if (win32_channel->debug) @@ -1305,7 +1353,7 @@ g_io_win32_fd_close (GIOChannel *channel, win32_channel->fd); win32_channel->fd = -1; } - UNLOCK (win32_channel->mutex); + LeaveCriticalSection (&win32_channel->mutex); /* FIXME error detection? */ @@ -1336,7 +1384,7 @@ g_io_win32_fd_create_watch (GIOChannel *channel, channel, win32_channel->fd, condition_to_string (condition), (HANDLE) watch->pollfd.fd); - LOCK (win32_channel->mutex); + EnterCriticalSection (&win32_channel->mutex); if (win32_channel->thread_id == 0) { if (condition & G_IO_IN) @@ -1346,7 +1394,7 @@ g_io_win32_fd_create_watch (GIOChannel *channel, } g_source_add_poll (source, &watch->pollfd); - UNLOCK (win32_channel->mutex); + LeaveCriticalSection (&win32_channel->mutex); return source; } @@ -1575,7 +1623,8 @@ g_io_channel_new_file (const gchar *filename, MODE_W = 1 << 1, MODE_A = 1 << 2, MODE_PLUS = 1 << 3, - } mode_num; + }; + int mode_num; g_return_val_if_fail (filename != NULL, NULL); g_return_val_if_fail (mode != NULL, NULL); @@ -1593,7 +1642,7 @@ g_io_channel_new_file (const gchar *filename, mode_num = MODE_A; break; default: - g_warning ("Invalid GIOFileMode %s.\n", mode); + g_warning ("Invalid GIOFileMode %s.", mode); return NULL; } @@ -1609,7 +1658,7 @@ g_io_channel_new_file (const gchar *filename, } /* Fall through */ default: - g_warning ("Invalid GIOFileMode %s.\n", mode); + g_warning ("Invalid GIOFileMode %s.", mode); return NULL; } @@ -1741,8 +1790,8 @@ g_io_win32_unimpl_set_flags (GIOChannel *channel, } static GIOFlags -g_io_win32_fd_get_flags_internal (GIOChannel *channel, - struct stat *st) +g_io_win32_fd_get_flags_internal (GIOChannel *channel, + struct _stati64 *st) { GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel; gchar c; @@ -1774,13 +1823,13 @@ g_io_win32_fd_get_flags_internal (GIOChannel *channel, static GIOFlags g_io_win32_fd_get_flags (GIOChannel *channel) { - struct stat st; + struct _stati64 st; GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel; g_return_val_if_fail (win32_channel != NULL, 0); g_return_val_if_fail (win32_channel->type == G_IO_WIN32_FILE_DESC, 0); - if (0 == fstat (win32_channel->fd, &st)) + if (0 == _fstati64 (win32_channel->fd, &st)) return g_io_win32_fd_get_flags_internal (channel, &st); else return 0; @@ -1919,6 +1968,17 @@ static GIOFuncs win32_channel_sock_funcs = { g_io_win32_sock_get_flags, }; +/** + * g_io_channel_win32_new_messages: + * @hwnd: a window handle. + * + * Creates a new #GIOChannel given a window handle on Windows. + * + * This function creates a #GIOChannel that can be used to poll for + * Windows messages for the window in question. + * + * Returns: a new #GIOChannel. + **/ GIOChannel * #if GLIB_SIZEOF_VOID_P == 8 g_io_channel_win32_new_messages (gsize hwnd) @@ -1948,8 +2008,8 @@ g_io_channel_win32_new_messages (guint hwnd) } static GIOChannel * -g_io_channel_win32_new_fd_internal (gint fd, - struct stat *st) +g_io_channel_win32_new_fd_internal (gint fd, + struct _stati64 *st) { GIOWin32Channel *win32_channel; GIOChannel *channel; @@ -1982,12 +2042,41 @@ g_io_channel_win32_new_fd_internal (gint fd, return channel; } +/** + * g_io_channel_win32_new_fd: + * @fd: a C library file descriptor. + * + * Creates a new #GIOChannel given a file descriptor on Windows. This + * works for file descriptors from the C runtime. + * + * This function works for file descriptors as returned by the open(), + * creat(), pipe() and fileno() calls in the Microsoft C runtime. In + * order to meaningfully use this function your code should use the + * same C runtime as GLib uses, which is msvcrt.dll. Note that in + * current Microsoft compilers it is near impossible to convince it to + * build code that would use msvcrt.dll. The last Microsoft compiler + * version that supported using msvcrt.dll as the C runtime was version + * 6. The GNU compiler and toolchain for Windows, also known as Mingw, + * fully supports msvcrt.dll. + * + * If you have created a #GIOChannel for a file descriptor and started + * watching (polling) it, you shouldn't call read() on the file + * descriptor. This is because adding polling for a file descriptor is + * implemented in GLib on Windows by starting a thread that sits + * blocked in a read() from the file descriptor most of the time. All + * reads from the file descriptor should be done by this internal GLib + * thread. Your code should call only g_io_channel_read(). + * + * This function is available only in GLib on Windows. + * + * Returns: a new #GIOChannel. + **/ GIOChannel * g_io_channel_win32_new_fd (gint fd) { - struct stat st; + struct _stati64 st; - if (fstat (fd, &st) == -1) + if (_fstati64 (fd, &st) == -1) { g_warning ("g_io_channel_win32_new_fd: %d isn't an open file descriptor in the C library GLib uses.", fd); return NULL; @@ -2004,6 +2093,21 @@ g_io_channel_win32_get_fd (GIOChannel *channel) return win32_channel->fd; } +/** + * g_io_channel_win32_new_socket: + * @socket: a Winsock socket + * + * Creates a new #GIOChannel given a socket on Windows. + * + * This function works for sockets created by Winsock. It's available + * only in GLib on Windows. + * + * Polling a #GSource created to watch a channel for a socket puts the + * socket in non-blocking mode. This is a side-effect of the + * implementation and unavoidable. + * + * Returns: a new #GIOChannel + **/ GIOChannel * g_io_channel_win32_new_socket (int socket) { @@ -2030,10 +2134,10 @@ GIOChannel * g_io_channel_unix_new (gint fd) { gboolean is_fd, is_socket; - struct stat st; + struct _stati64 st; int optval, optlen; - is_fd = (fstat (fd, &st) == 0); + is_fd = (_fstati64 (fd, &st) == 0); optlen = sizeof (optval); is_socket = (getsockopt (fd, SOL_SOCKET, SO_TYPE, (char *) &optval, &optlen) != SOCKET_ERROR); @@ -2072,13 +2176,9 @@ g_io_channel_win32_poll (GPollFD *fds, gint n_fds, gint timeout) { - int result; - g_return_val_if_fail (n_fds >= 0, 0); - result = (*g_main_context_get_poll_func (NULL)) (fds, n_fds, timeout); - - return result; + return g_poll (fds, n_fds, timeout); } void @@ -2131,6 +2231,8 @@ g_io_channel_win32_make_pollfd (GIOChannel *channel, fd->events = condition; } +#ifndef _WIN64 + /* Binary compatibility */ GIOChannel * g_io_channel_win32_new_stream_socket (int socket) @@ -2138,5 +2240,4 @@ g_io_channel_win32_new_stream_socket (int socket) return g_io_channel_win32_new_socket (socket); } -#define __G_IO_WIN32_C__ -#include "galiasdef.c" +#endif