OSDN Git Service

Add emulation of non-blocking sockets to the win32 socket/signal layer,
authorMagnus Hagander <magnus@hagander.net>
Tue, 16 Feb 2010 19:26:02 +0000 (19:26 +0000)
committerMagnus Hagander <magnus@hagander.net>
Tue, 16 Feb 2010 19:26:02 +0000 (19:26 +0000)
and use this in pq_getbyte_if_available.

It's only a limited implementation which swithes the whole emulation layer
no non-blocking mode, but that's enough as long as non-blocking is only
used during a short period of time, and only one socket is accessed during
this time.

src/backend/libpq/pqcomm.c
src/backend/port/win32/socket.c
src/include/port/win32.h

index f4e6974..8f40c93 100644 (file)
@@ -30,7 +30,7 @@
  * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- *     $PostgreSQL: pgsql/src/backend/libpq/pqcomm.c,v 1.202 2010/01/15 09:19:02 heikki Exp $
+ *     $PostgreSQL: pgsql/src/backend/libpq/pqcomm.c,v 1.203 2010/02/16 19:26:02 mha Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -837,9 +837,13 @@ pq_getbyte_if_available(unsigned char *c)
        }
 
        /* Temporarily put the socket into non-blocking mode */
+#ifdef WIN32
+       pgwin32_noblock = 1;
+#else
        if (!pg_set_noblock(MyProcPort->sock))
                ereport(ERROR,
                                (errmsg("couldn't put socket to non-blocking mode: %m")));
+#endif
        MyProcPort->noblock = true;
        PG_TRY();
        {
@@ -851,16 +855,24 @@ pq_getbyte_if_available(unsigned char *c)
                 * The rest of the backend code assumes the socket is in blocking
                 * mode, so treat failure as FATAL.
                 */
+#ifdef WIN32
+               pgwin32_noblock = 0;
+#else
                if (!pg_set_block(MyProcPort->sock))
                        ereport(FATAL,
                                        (errmsg("couldn't put socket to blocking mode: %m")));
+#endif
                MyProcPort->noblock = false;
                PG_RE_THROW();
        }
        PG_END_TRY();
+#ifdef WIN32
+       pgwin32_noblock = 0;
+#else
        if (!pg_set_block(MyProcPort->sock))
                ereport(FATAL,
                                (errmsg("couldn't put socket to blocking mode: %m")));
+#endif
        MyProcPort->noblock = false;
 
        return r;
index 8076b8c..af42576 100644 (file)
@@ -6,13 +6,26 @@
  * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/port/win32/socket.c,v 1.23 2010/01/02 16:57:50 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/port/win32/socket.c,v 1.24 2010/02/16 19:26:02 mha Exp $
  *
  *-------------------------------------------------------------------------
  */
 
 #include "postgres.h"
 
+/*
+ * Indicate if pgwin32_recv() should operate in non-blocking mode.
+ *
+ * Since the socket emulation layer always sets the actual socket to
+ * non-blocking mode in order to be able to deliver signals, we must
+ * specify this in a separate flag if we actually need non-blocking
+ * operation.
+ *
+ * This flag changes the behaviour *globally* for all socket operations,
+ * so it should only be set for very short periods of time.
+ */
+int    pgwin32_noblock = 0;
+
 #undef socket
 #undef accept
 #undef connect
@@ -310,6 +323,16 @@ pgwin32_recv(SOCKET s, char *buf, int len, int f)
                return -1;
        }
 
+       if (pgwin32_noblock)
+       {
+               /*
+                * No data received, and we are in "emulated non-blocking mode", so return
+                * indicating thta we'd block if we were to continue.
+                */
+               errno = EWOULDBLOCK;
+               return -1;
+       }
+
        /* No error, zero bytes (win2000+) or error+WSAEWOULDBLOCK (<=nt4) */
 
        for (n = 0; n < 5; n++)
index 3ec81c4..6dbda80 100644 (file)
@@ -1,4 +1,4 @@
-/* $PostgreSQL: pgsql/src/include/port/win32.h,v 1.92 2010/02/13 02:34:14 tgl Exp $ */
+/* $PostgreSQL: pgsql/src/include/port/win32.h,v 1.93 2010/02/16 19:26:02 mha Exp $ */
 
 #if defined(_MSC_VER) || defined(__BORLANDC__)
 #define WIN32_ONLY_COMPILER
@@ -283,6 +283,8 @@ int                 pgwin32_send(SOCKET s, char *buf, int len, int flags);
 const char *pgwin32_socket_strerror(int err);
 int                    pgwin32_waitforsinglesocket(SOCKET s, int what, int timeout);
 
+extern int     pgwin32_noblock;
+
 /* in backend/port/win32/security.c */
 extern int     pgwin32_is_admin(void);
 extern int     pgwin32_is_service(void);