Re: [HACKERS] Re: WIN32 errno patch

Bruce Momjian <pgman@candle.pha.pa.us>

From: Bruce Momjian <pgman@candle.pha.pa.us>
To: Mikhail Terekhov <terekhov@emc.com>
Cc: Tom Lane <tgl@sss.pgh.pa.us>, PostgreSQL-patches <pgsql-patches@postgresql.org>
Date: 2001-08-17T14:47:49Z
Lists: pgsql-hackers
Your patch has been added to the PostgreSQL unapplied patches list at:

	http://candle.pha.pa.us/cgi-bin/pgpatches

I will try to apply it within the next 48 hours.

> 
> 
> Tom Lane wrote:
> > 
> > When someone sends me a Windoze implementation of the proposed
> > SOCK_STRERROR() macro, I'll see about fixing it.  Till then
> > I can't do much.
> > 
> >                         regards, tom lane
> > 
> 
> Could you please review the following patch for libpq.
> I've implemented the SOCK_ERRNO macro only because
> both strerror and FormatMessage functions know nothing
> about sockets errors.
> I've compiled the current sources with this patch applied
> on windows and Solaris without problems and tested it through
> tcl interface only. It seems to work correctly - I could insert
> and select large strings (>10k).
> 
> Regards
> Mikhail Terekhov
> 
> 
> Index: libpq/fe-connect.c
> ===================================================================
> RCS file: /home/projects/pgsql/cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v
> retrieving revision 1.172
> diff -C3 -r1.172 fe-connect.c
> *** libpq/fe-connect.c	2001/08/03 22:11:39	1.172
> --- libpq/fe-connect.c	2001/08/15 13:58:32
> ***************
> *** 711,717 ****
>   	{
>   		printfPQExpBuffer(&conn->errorMessage,
>   						  libpq_gettext("could not set socket to non-blocking mode: %s\n"),
> ! 						  strerror(errno));
>   		return 0;
>   	}
>   
> --- 711,717 ----
>   	{
>   		printfPQExpBuffer(&conn->errorMessage,
>   						  libpq_gettext("could not set socket to non-blocking mode: %s\n"),
> ! 						  strerror(SOCK_ERRNO));
>   		return 0;
>   	}
>   
> ***************
> *** 735,741 ****
>   	{
>   		printfPQExpBuffer(&conn->errorMessage,
>   						  libpq_gettext("could not set socket to TCP no delay mode: %s\n"),
> ! 						  strerror(errno));
>   		return 0;
>   	}
>   
> --- 735,741 ----
>   	{
>   		printfPQExpBuffer(&conn->errorMessage,
>   						  libpq_gettext("could not set socket to TCP no delay mode: %s\n"),
> ! 						  strerror(SOCK_ERRNO));
>   		return 0;
>   	}
>   
> ***************
> *** 890,896 ****
>   	{
>   		printfPQExpBuffer(&conn->errorMessage,
>   						  libpq_gettext("could not create socket: %s\n"),
> ! 						  strerror(errno));
>   		goto connect_errReturn;
>   	}
>   
> --- 890,896 ----
>   	{
>   		printfPQExpBuffer(&conn->errorMessage,
>   						  libpq_gettext("could not create socket: %s\n"),
> ! 						  strerror(SOCK_ERRNO));
>   		goto connect_errReturn;
>   	}
>   
> ***************
> *** 922,928 ****
>   	 */
>   	if (connect(conn->sock, &conn->raddr.sa, conn->raddr_len) < 0)
>   	{
> ! 		if (errno == EINPROGRESS || errno == EWOULDBLOCK || errno == 0)
>   		{
>   			/*
>   			 * This is fine - we're in non-blocking mode, and the
> --- 922,928 ----
>   	 */
>   	if (connect(conn->sock, &conn->raddr.sa, conn->raddr_len) < 0)
>   	{
> ! 		if (SOCK_ERRNO == EINPROGRESS || SOCK_ERRNO == EWOULDBLOCK || errno == 0)
>   		{
>   			/*
>   			 * This is fine - we're in non-blocking mode, and the
> ***************
> *** 933,939 ****
>   		else
>   		{
>   			/* Something's gone wrong */
> ! 			connectFailureMessage(conn, errno);
>   			goto connect_errReturn;
>   		}
>   	}
> --- 933,939 ----
>   		else
>   		{
>   			/* Something's gone wrong */
> ! 			connectFailureMessage(conn, SOCK_ERRNO);
>   			goto connect_errReturn;
>   		}
>   	}
> ***************
> *** 1212,1218 ****
>   				{
>   					printfPQExpBuffer(&conn->errorMessage,
>   									  libpq_gettext("could not get socket error status: %s\n"),
> ! 									  strerror(errno));
>   					goto error_return;
>   				}
>   				else if (optval != 0)
> --- 1212,1218 ----
>   				{
>   					printfPQExpBuffer(&conn->errorMessage,
>   									  libpq_gettext("could not get socket error status: %s\n"),
> ! 									  strerror(SOCK_ERRNO));
>   					goto error_return;
>   				}
>   				else if (optval != 0)
> ***************
> *** 1232,1238 ****
>   				{
>   					printfPQExpBuffer(&conn->errorMessage,
>   									  libpq_gettext("could not get client address from socket: %s\n"),
> ! 									  strerror(errno));
>   					goto error_return;
>   				}
>   
> --- 1232,1238 ----
>   				{
>   					printfPQExpBuffer(&conn->errorMessage,
>   									  libpq_gettext("could not get client address from socket: %s\n"),
> ! 									  strerror(SOCK_ERRNO));
>   					goto error_return;
>   				}
>   
> ***************
> *** 1271,1277 ****
>   				{
>   					printfPQExpBuffer(&conn->errorMessage,
>   									  libpq_gettext("could not send startup packet: %s\n"),
> ! 									  strerror(errno));
>   					goto error_return;
>   				}
>   
> --- 1271,1277 ----
>   				{
>   					printfPQExpBuffer(&conn->errorMessage,
>   									  libpq_gettext("could not send startup packet: %s\n"),
> ! 									  strerror(SOCK_ERRNO));
>   					goto error_return;
>   				}
>   
> ***************
> *** 2101,2107 ****
>   int
>   PQrequestCancel(PGconn *conn)
>   {
> ! 	int			save_errno = errno;
>   	int			tmpsock = -1;
>   	struct
>   	{
> --- 2101,2107 ----
>   int
>   PQrequestCancel(PGconn *conn)
>   {
> ! 	int			save_errno = SOCK_ERRNO;
>   	int			tmpsock = -1;
>   	struct
>   	{
> ***************
> *** 2173,2179 ****
>   	return TRUE;
>   
>   cancel_errReturn:
> ! 	strcat(conn->errorMessage.data, strerror(errno));
>   	strcat(conn->errorMessage.data, "\n");
>   	conn->errorMessage.len = strlen(conn->errorMessage.data);
>   	if (tmpsock >= 0)
> --- 2173,2179 ----
>   	return TRUE;
>   
>   cancel_errReturn:
> ! 	strcat(conn->errorMessage.data, strerror(SOCK_ERRNO));
>   	strcat(conn->errorMessage.data, "\n");
>   	conn->errorMessage.len = strlen(conn->errorMessage.data);
>   	if (tmpsock >= 0)
> Index: libpq/fe-exec.c
> ===================================================================
> RCS file: /home/projects/pgsql/cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v
> retrieving revision 1.105
> diff -C3 -r1.105 fe-exec.c
> *** libpq/fe-exec.c	2001/08/03 22:11:39	1.105
> --- libpq/fe-exec.c	2001/08/15 13:58:32
> ***************
> *** 2037,2046 ****
>   	return buf;
>   }
>   
> - #ifdef WIN32					/* need to get at normal errno here */
> - #undef errno
> - #endif
> - 
>   /*
>     PQoidValue -
>   		a perhaps preferable form of the above which just returns
> --- 2037,2042 ----
> ***************
> *** 2055,2061 ****
> --- 2051,2061 ----
>   	if (!res || !res->cmdStatus || strncmp(res->cmdStatus, "INSERT ", 7) != 0)
>   		return InvalidOid;
>   
> + #ifdef WIN32
> +     SetLastError(0);
> + #else
>   	errno = 0;
> + #endif
>   	result = strtoul(res->cmdStatus + 7, &endptr, 10);
>   
>   	if (!endptr || (*endptr != ' ' && *endptr != '\0') || errno == ERANGE)
> ***************
> *** 2064,2072 ****
>   		return (Oid) result;
>   }
>   
> - #ifdef WIN32					/* back to socket errno */
> - #define errno WSAGetLastError()
> - #endif
>   
>   /*
>      PQcmdTuples -
> --- 2064,2069 ----
> Index: libpq/fe-lobj.c
> ===================================================================
> RCS file: /home/projects/pgsql/cvsroot/pgsql/src/interfaces/libpq/fe-lobj.c,v
> retrieving revision 1.36
> diff -C3 -r1.36 fe-lobj.c
> *** libpq/fe-lobj.c	2001/08/03 22:11:39	1.36
> --- libpq/fe-lobj.c	2001/08/15 13:58:32
> ***************
> *** 30,41 ****
>   
>   #include "libpq/libpq-fs.h"		/* must come after sys/stat.h */
>   
> - 
> - #ifdef WIN32					/* need to use normal errno in this file */
> - #undef errno
> - #endif
> - 
> - 
>   #define LO_BUFSIZE		  8192
>   
>   static int	lo_initialize(PGconn *conn);
> --- 30,35 ----
> Index: libpq/fe-misc.c
> ===================================================================
> RCS file: /home/projects/pgsql/cvsroot/pgsql/src/interfaces/libpq/fe-misc.c,v
> retrieving revision 1.52
> diff -C3 -r1.52 fe-misc.c
> *** libpq/fe-misc.c	2001/07/20 17:45:06	1.52
> --- libpq/fe-misc.c	2001/08/15 13:58:32
> ***************
> *** 347,359 ****
>   	if (select(conn->sock + 1, &input_mask, (fd_set *) NULL, (fd_set *) NULL,
>   			   &timeout) < 0)
>   	{
> ! 		if (errno == EINTR)
>   			/* Interrupted system call - we'll just try again */
>   			goto retry;
>   
>   		printfPQExpBuffer(&conn->errorMessage,
>   						  libpq_gettext("select() failed: %s\n"),
> ! 						  strerror(errno));
>   		return -1;
>   	}
>   
> --- 347,359 ----
>   	if (select(conn->sock + 1, &input_mask, (fd_set *) NULL, (fd_set *) NULL,
>   			   &timeout) < 0)
>   	{
> ! 		if (SOCK_ERRNO == EINTR)
>   			/* Interrupted system call - we'll just try again */
>   			goto retry;
>   
>   		printfPQExpBuffer(&conn->errorMessage,
>   						  libpq_gettext("select() failed: %s\n"),
> ! 						  strerror(SOCK_ERRNO));
>   		return -1;
>   	}
>   
> ***************
> *** 381,393 ****
>   	if (select(conn->sock + 1, (fd_set *) NULL, &input_mask, (fd_set *) NULL,
>   			   &timeout) < 0)
>   	{
> ! 		if (errno == EINTR)
>   			/* Interrupted system call - we'll just try again */
>   			goto retry;
>   
>   		printfPQExpBuffer(&conn->errorMessage,
>   						  libpq_gettext("select() failed: %s\n"),
> ! 						  strerror(errno));
>   		return -1;
>   	}
>   	return FD_ISSET(conn->sock, &input_mask) ? 1 : 0;
> --- 381,393 ----
>   	if (select(conn->sock + 1, (fd_set *) NULL, &input_mask, (fd_set *) NULL,
>   			   &timeout) < 0)
>   	{
> ! 		if (SOCK_ERRNO == EINTR)
>   			/* Interrupted system call - we'll just try again */
>   			goto retry;
>   
>   		printfPQExpBuffer(&conn->errorMessage,
>   						  libpq_gettext("select() failed: %s\n"),
> ! 						  strerror(SOCK_ERRNO));
>   		return -1;
>   	}
>   	return FD_ISSET(conn->sock, &input_mask) ? 1 : 0;
> ***************
> *** 466,490 ****
>   					 conn->inBufSize - conn->inEnd, 0);
>   	if (nread < 0)
>   	{
> ! 		if (errno == EINTR)
>   			goto tryAgain;
>   		/* Some systems return EAGAIN/EWOULDBLOCK for no data */
>   #ifdef EAGAIN
> ! 		if (errno == EAGAIN)
>   			return someread;
>   #endif
>   #if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
> ! 		if (errno == EWOULDBLOCK)
>   			return someread;
>   #endif
>   		/* We might get ECONNRESET here if using TCP and backend died */
>   #ifdef ECONNRESET
> ! 		if (errno == ECONNRESET)
>   			goto definitelyFailed;
>   #endif
>   		printfPQExpBuffer(&conn->errorMessage,
>   						  libpq_gettext("could not receive data from server: %s\n"),
> ! 						  strerror(errno));
>   		return -1;
>   	}
>   	if (nread > 0)
> --- 466,490 ----
>   					 conn->inBufSize - conn->inEnd, 0);
>   	if (nread < 0)
>   	{
> ! 		if (SOCK_ERRNO == EINTR)
>   			goto tryAgain;
>   		/* Some systems return EAGAIN/EWOULDBLOCK for no data */
>   #ifdef EAGAIN
> ! 		if (SOCK_ERRNO == EAGAIN)
>   			return someread;
>   #endif
>   #if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
> ! 		if (SOCK_ERRNO == EWOULDBLOCK)
>   			return someread;
>   #endif
>   		/* We might get ECONNRESET here if using TCP and backend died */
>   #ifdef ECONNRESET
> ! 		if (SOCK_ERRNO == ECONNRESET)
>   			goto definitelyFailed;
>   #endif
>   		printfPQExpBuffer(&conn->errorMessage,
>   						  libpq_gettext("could not receive data from server: %s\n"),
> ! 						  strerror(SOCK_ERRNO));
>   		return -1;
>   	}
>   	if (nread > 0)
> ***************
> *** 552,576 ****
>   					 conn->inBufSize - conn->inEnd, 0);
>   	if (nread < 0)
>   	{
> ! 		if (errno == EINTR)
>   			goto tryAgain2;
>   		/* Some systems return EAGAIN/EWOULDBLOCK for no data */
>   #ifdef EAGAIN
> ! 		if (errno == EAGAIN)
>   			return 0;
>   #endif
>   #if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
> ! 		if (errno == EWOULDBLOCK)
>   			return 0;
>   #endif
>   		/* We might get ECONNRESET here if using TCP and backend died */
>   #ifdef ECONNRESET
> ! 		if (errno == ECONNRESET)
>   			goto definitelyFailed;
>   #endif
>   		printfPQExpBuffer(&conn->errorMessage,
>   						  libpq_gettext("could not receive data from server: %s\n"),
> ! 						  strerror(errno));
>   		return -1;
>   	}
>   	if (nread > 0)
> --- 552,576 ----
>   					 conn->inBufSize - conn->inEnd, 0);
>   	if (nread < 0)
>   	{
> ! 		if (SOCK_ERRNO == EINTR)
>   			goto tryAgain2;
>   		/* Some systems return EAGAIN/EWOULDBLOCK for no data */
>   #ifdef EAGAIN
> ! 		if (SOCK_ERRNO == EAGAIN)
>   			return 0;
>   #endif
>   #if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
> ! 		if (SOCK_ERRNO == EWOULDBLOCK)
>   			return 0;
>   #endif
>   		/* We might get ECONNRESET here if using TCP and backend died */
>   #ifdef ECONNRESET
> ! 		if (SOCK_ERRNO == ECONNRESET)
>   			goto definitelyFailed;
>   #endif
>   		printfPQExpBuffer(&conn->errorMessage,
>   						  libpq_gettext("could not receive data from server: %s\n"),
> ! 						  strerror(SOCK_ERRNO));
>   		return -1;
>   	}
>   	if (nread > 0)
> ***************
> *** 652,658 ****
>   			 * EPIPE or ECONNRESET, assume we've lost the backend
>   			 * connection permanently.
>   			 */
> ! 			switch (errno)
>   			{
>   #ifdef EAGAIN
>   				case EAGAIN:
> --- 652,658 ----
>   			 * EPIPE or ECONNRESET, assume we've lost the backend
>   			 * connection permanently.
>   			 */
> ! 			switch (SOCK_ERRNO)
>   			{
>   #ifdef EAGAIN
>   				case EAGAIN:
> ***************
> *** 688,694 ****
>   				default:
>   					printfPQExpBuffer(&conn->errorMessage,
>   									  libpq_gettext("could not send data to server: %s\n"),
> ! 									  strerror(errno));
>   					/* We don't assume it's a fatal error... */
>   					return EOF;
>   			}
> --- 688,694 ----
>   				default:
>   					printfPQExpBuffer(&conn->errorMessage,
>   									  libpq_gettext("could not send data to server: %s\n"),
> ! 									  strerror(SOCK_ERRNO));
>   					/* We don't assume it's a fatal error... */
>   					return EOF;
>   			}
> ***************
> *** 771,781 ****
>   		if (select(conn->sock + 1, &input_mask, &output_mask, &except_mask,
>   				   (struct timeval *) NULL) < 0)
>   		{
> ! 			if (errno == EINTR)
>   				goto retry;
>   			printfPQExpBuffer(&conn->errorMessage,
>   							  libpq_gettext("select() failed: %s\n"),
> ! 							  strerror(errno));
>   			return EOF;
>   		}
>   	}
> --- 771,781 ----
>   		if (select(conn->sock + 1, &input_mask, &output_mask, &except_mask,
>   				   (struct timeval *) NULL) < 0)
>   		{
> ! 			if (SOCK_ERRNO == EINTR)
>   				goto retry;
>   			printfPQExpBuffer(&conn->errorMessage,
>   							  libpq_gettext("select() failed: %s\n"),
> ! 							  strerror(SOCK_ERRNO));
>   			return EOF;
>   		}
>   	}
> Index: libpq/libpq-fe.h
> ===================================================================
> RCS file: /home/projects/pgsql/cvsroot/pgsql/src/interfaces/libpq/libpq-fe.h,v
> retrieving revision 1.71
> diff -C3 -r1.71 libpq-fe.h
> *** libpq/libpq-fe.h	2001/03/22 04:01:27	1.71
> --- libpq/libpq-fe.h	2001/08/15 13:58:32
> ***************
> *** 21,30 ****
> --- 21,39 ----
>   #endif
>   
>   #include <stdio.h>
> + 
> + #ifdef WIN32
> +     #define SOCK_ERRNO (WSAGetLastError ())
> + #else
> +     #define SOCK_ERRNO errno
> + #endif
> + 
> + 
>   /* postgres_ext.h defines the backend's externally visible types,
>    * such as Oid.
>    */
>   #include "postgres_ext.h"
> + 
>   #ifdef USE_SSL
>   #include <openssl/ssl.h>
>   #endif
> Index: libpq/win32.h
> ===================================================================
> RCS file: /home/projects/pgsql/cvsroot/pgsql/src/interfaces/libpq/win32.h,v
> retrieving revision 1.15
> diff -C3 -r1.15 win32.h
> *** libpq/win32.h	2001/08/03 22:11:39	1.15
> --- libpq/win32.h	2001/08/15 13:58:32
> ***************
> *** 23,38 ****
>    */
>   #define crypt(a,b) (a)
>   
> - /*
> -  * Most of libpq uses "errno" to access error conditions from socket calls,
> -  * so on Windows we want to redirect those usages to WSAGetLastError().
> -  * Rather than #ifdef'ing every single place that has "errno", hack it up
> -  * with a macro instead.  But there are a few places that do need to touch
> -  * the regular errno variable.  For them, we #undef and then redefine errno.
> -  */
> - 
> - #define errno WSAGetLastError()
> - 
>   #undef EAGAIN	/* doesn't apply on sockets */
>   #undef EINTR
>   #define EINTR WSAEINTR
> --- 23,28 ----
> 
> ---------------------------(end of broadcast)---------------------------
> TIP 5: Have you checked our extensive FAQ?
> 
> http://www.postgresql.org/users-lounge/docs/faq.html
> 

-- 
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 853-3000
  +  If your life is a hard drive,     |  830 Blythe Avenue
  +  Christ can be your backup.        |  Drexel Hill, Pennsylvania 19026