Thread: Proposed replacement for pipe under Win32

Proposed replacement for pipe under Win32

From
Claudio Natoli
Date:
To go in src/port/ directory.

This is to allow the handles returned by pipe to be used in select() calls
(which Win32 doesn't allow with the native pipe() call), thereby obviating
the need for reworking of the select() mechanisms in pgstat.c.

Additionally, something of the sort would be required at the top of pgstat.c

#ifdef WIN32
#define pipe(a)        pgpipe(a)
#define write(a,b,c)    send(a,b,c,0)
#define read(a,b,c)     recv(a,b,c,0)
#endif

For reference, see this thread:
http://archives.postgresql.org/pgsql-hackers/2003-12/msg00650.php

Cheers,
Claudio






---
Certain disclaimers and policies apply to all email sent from Memetrics.
For the full text of these disclaimers and policies see
<a
href="http://www.memetrics.com/emailpolicy.html">http://www.memetrics.com/em
ailpolicy.html</a>



Attachment

Re: Proposed replacement for pipe under Win32

From
Bruce Momjian
Date:
I have applied your new pipe.c file, the macros you listed (with
modification), and the configure glue to make it work.

Patch and new file attached and applied.

---------------------------------------------------------------------------

Claudio Natoli wrote:
>
> To go in src/port/ directory.
>
> This is to allow the handles returned by pipe to be used in select() calls
> (which Win32 doesn't allow with the native pipe() call), thereby obviating
> the need for reworking of the select() mechanisms in pgstat.c.
>
> Additionally, something of the sort would be required at the top of pgstat.c
>
> #ifdef WIN32
> #define pipe(a)        pgpipe(a)
> #define write(a,b,c)    send(a,b,c,0)
> #define read(a,b,c)     recv(a,b,c,0)
> #endif
>
> For reference, see this thread:
> http://archives.postgresql.org/pgsql-hackers/2003-12/msg00650.php

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073
Index: configure
===================================================================
RCS file: /cvsroot/pgsql-server/configure,v
retrieving revision 1.319
diff -c -c -r1.319 configure
*** configure    23 Dec 2003 18:40:51 -0000    1.319
--- configure    9 Jan 2004 03:48:13 -0000
***************
*** 12227,12233 ****
  case $host_os in mingw*)
  LIBOBJS="$LIBOBJS dirmod.$ac_objext"
  LIBOBJS="$LIBOBJS copydir.$ac_objext"
! LIBOBJS="$LIBOBJS gettimeofday.$ac_objext" ;;
  esac

  if test "$with_readline" = yes; then
--- 12227,12234 ----
  case $host_os in mingw*)
  LIBOBJS="$LIBOBJS dirmod.$ac_objext"
  LIBOBJS="$LIBOBJS copydir.$ac_objext"
! LIBOBJS="$LIBOBJS gettimeofday.$ac_objext"
! LIBOBJS="$LIBOBJS pipe.$ac_objext" ;;
  esac

  if test "$with_readline" = yes; then
Index: configure.in
===================================================================
RCS file: /cvsroot/pgsql-server/configure.in,v
retrieving revision 1.309
diff -c -c -r1.309 configure.in
*** configure.in    23 Dec 2003 18:40:52 -0000    1.309
--- configure.in    9 Jan 2004 03:48:14 -0000
***************
*** 924,930 ****
  case $host_os in mingw*)
  AC_LIBOBJ(dirmod)
  AC_LIBOBJ(copydir)
! AC_LIBOBJ(gettimeofday) ;;
  esac

  if test "$with_readline" = yes; then
--- 924,931 ----
  case $host_os in mingw*)
  AC_LIBOBJ(dirmod)
  AC_LIBOBJ(copydir)
! AC_LIBOBJ(gettimeofday)
! AC_LIBOBJ(pipe) ;;
  esac

  if test "$with_readline" = yes; then
Index: src/backend/postmaster/pgstat.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/postmaster/pgstat.c,v
retrieving revision 1.51
diff -c -c -r1.51 pgstat.c
*** src/backend/postmaster/pgstat.c    6 Jan 2004 23:15:22 -0000    1.51
--- src/backend/postmaster/pgstat.c    9 Jan 2004 03:48:16 -0000
***************
*** 135,140 ****
--- 135,153 ----
  static void pgstat_recv_dropdb(PgStat_MsgDropdb *msg, int len);
  static void pgstat_recv_resetcounter(PgStat_MsgResetcounter *msg, int len);

+ /*
+  *    WIN32 doesn't allow descriptors returned by pipe() to be used in select(),
+  *    so for that platform we use socket() instead of pipe().
+  */
+ #ifndef WIN32
+ #define pgpipe(a)            pipe(a)
+ #define piperead(a,b,c)        read(a,b,c)
+ #define pipewrite(a,b,c)    write(a,b,c)
+ #else
+ /* pgpipe() is in /src/port */
+ #define piperead(a,b,c)        recv(a,b,c,0)
+ #define pipewrite(a,b,c)    send(a,b,c,0)
+ #endif

  /* ------------------------------------------------------------
   * Public functions called from postmaster follow
***************
*** 1380,1386 ****
       * two buffer processes competing to read from the UDP socket --- not
       * good.
       */
!     if (pipe(pgStatPipe) < 0)
      {
          ereport(LOG,
                  (errcode_for_socket_access(),
--- 1393,1399 ----
       * two buffer processes competing to read from the UDP socket --- not
       * good.
       */
!     if (pgpipe(pgStatPipe) < 0)
      {
          ereport(LOG,
                  (errcode_for_socket_access(),
***************
*** 1595,1601 ****

              while (nread < targetlen)
              {
!                 len = read(readPipe,
                             ((char *) &msg) + nread,
                             targetlen - nread);
                  if (len < 0)
--- 1608,1614 ----

              while (nread < targetlen)
              {
!                 len = piperead(readPipe,
                             ((char *) &msg) + nread,
                             targetlen - nread);
                  if (len < 0)
***************
*** 1920,1926 ****
              if (xfr > msg_have)
                  xfr = msg_have;
              Assert(xfr > 0);
!             len = write(writePipe, msgbuffer + msg_send, xfr);
              if (len < 0)
              {
                  if (errno == EINTR || errno == EAGAIN)
--- 1933,1939 ----
              if (xfr > msg_have)
                  xfr = msg_have;
              Assert(xfr > 0);
!             len = pipewrite(writePipe, msgbuffer + msg_send, xfr);
              if (len < 0)
              {
                  if (errno == EINTR || errno == EAGAIN)
/*-------------------------------------------------------------------------
 *
 * pipe.c
 *      pipe()
 *
 * Copyright (c) 1996-2003, PostgreSQL Global Development Group
 *
 *    This is a replacement version of pipe for Win32 which allows
 *    returned handles to be used in select(). Note that read/write calls
 *    must be replaced with recv/send.
 *
 * IDENTIFICATION
 *      $PostgreSQL: pgsql-server/src/port/pipe.c,v 1.1 2004/01/09 04:58:09 momjian Exp $
 *
 *-------------------------------------------------------------------------
 */

#include "postgres.h"

int
pgpipe(int handles[2])
{
    SOCKET        s;
    struct sockaddr_in serv_addr;
    int            len = sizeof(serv_addr);

    handles[0] = handles[1] = INVALID_SOCKET;

    if ((s = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
        return -1;

    memset((void *) &serv_addr, 0, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(0);
    serv_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
    if (bind(s, (SOCKADDR *) & serv_addr, len) == SOCKET_ERROR ||
        listen(s, 1) == SOCKET_ERROR ||
        getsockname(s, (SOCKADDR *) & serv_addr, &len) == SOCKET_ERROR ||
        (handles[1] = socket(PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
    {
        closesocket(s);
        return -1;
    }

    if (connect(handles[1], (SOCKADDR *) & serv_addr, len) == SOCKET_ERROR ||
        (handles[0] = accept(s, (SOCKADDR *) & serv_addr, &len)) == INVALID_SOCKET)
    {
        closesocket(handles[1]);
        handles[1] = INVALID_SOCKET;
        closesocket(s);
        return -1;
    }
    closesocket(s);
    return 0;
}