30
30
* Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
31
31
* Portions Copyright (c) 1994, Regents of the University of California
32
32
*
33
- * $PostgreSQL: pgsql/src/backend/libpq/pqcomm.c,v 1.171 2004/08/29 05:06:43 momjian Exp $
33
+ * $PostgreSQL: pgsql/src/backend/libpq/pqcomm.c,v 1.172 2004/09/26 00:26:19 tgl Exp $
34
34
*
35
35
*-------------------------------------------------------------------------
36
36
*/
44
44
* StreamClose - Close a client/backend connection
45
45
* TouchSocketFile - Protect socket file against /tmp cleaners
46
46
* pq_init - initialize libpq at backend startup
47
+ * pq_comm_reset - reset libpq during error recovery
47
48
* pq_close - shutdown libpq at backend exit
48
49
*
49
50
* low-level I/O:
88
89
#include "storage/ipc.h"
89
90
90
91
91
- static void pq_close (int code , Datum arg );
92
-
93
- #ifdef HAVE_UNIX_SOCKETS
94
- static int Lock_AF_UNIX (unsigned short portNumber , char * unixSocketName );
95
- static int Setup_AF_UNIX (void );
96
- #endif /* HAVE_UNIX_SOCKETS */
97
-
98
-
99
92
/*
100
93
* Configuration options
101
94
*/
102
95
int Unix_socket_permissions ;
103
96
char * Unix_socket_group ;
104
97
105
98
99
+ /* Where the Unix socket file is */
100
+ static char sock_path [MAXPGPATH ];
101
+
102
+
106
103
/*
107
104
* Buffers for low-level I/O
108
105
*/
@@ -121,9 +118,20 @@ static int PqRecvLength; /* End of data available in PqRecvBuffer */
121
118
/*
122
119
* Message status
123
120
*/
121
+ static bool PqCommBusy ;
124
122
static bool DoingCopyOut ;
125
123
126
124
125
+ /* Internal functions */
126
+ static void pq_close (int code , Datum arg );
127
+ static int internal_putbytes (const char * s , size_t len );
128
+ static int internal_flush (void );
129
+ #ifdef HAVE_UNIX_SOCKETS
130
+ static int Lock_AF_UNIX (unsigned short portNumber , char * unixSocketName );
131
+ static int Setup_AF_UNIX (void );
132
+ #endif /* HAVE_UNIX_SOCKETS */
133
+
134
+
127
135
/* --------------------------------
128
136
* pq_init - initialize libpq at backend startup
129
137
* --------------------------------
@@ -132,10 +140,27 @@ void
132
140
pq_init (void )
133
141
{
134
142
PqSendPointer = PqRecvPointer = PqRecvLength = 0 ;
143
+ PqCommBusy = false;
135
144
DoingCopyOut = false;
136
145
on_proc_exit (pq_close , 0 );
137
146
}
138
147
148
+ /* --------------------------------
149
+ * pq_comm_reset - reset libpq during error recovery
150
+ *
151
+ * This is called from error recovery at the outer idle loop. It's
152
+ * just to get us out of trouble if we somehow manage to elog() from
153
+ * inside a pqcomm.c routine (which ideally will never happen, but...)
154
+ * --------------------------------
155
+ */
156
+ void
157
+ pq_comm_reset (void )
158
+ {
159
+ /* Do not throw away pending data, but do reset the busy flag */
160
+ PqCommBusy = false;
161
+ /* We can abort any old-style COPY OUT, too */
162
+ pq_endcopyout (true);
163
+ }
139
164
140
165
/* --------------------------------
141
166
* pq_close - shutdown libpq at backend exit
@@ -174,8 +199,6 @@ pq_close(int code, Datum arg)
174
199
* Stream functions are used for vanilla TCP connection protocol.
175
200
*/
176
201
177
- static char sock_path [MAXPGPATH ];
178
-
179
202
180
203
/* StreamDoUnlink()
181
204
* Shutdown routine for backend connection
@@ -885,13 +908,30 @@ pq_getmessage(StringInfo s, int maxlen)
885
908
*/
886
909
int
887
910
pq_putbytes (const char * s , size_t len )
911
+ {
912
+ int res ;
913
+
914
+ /* Should only be called by old-style COPY OUT */
915
+ Assert (DoingCopyOut );
916
+ /* No-op if reentrant call */
917
+ if (PqCommBusy )
918
+ return 0 ;
919
+ PqCommBusy = true;
920
+ res = internal_putbytes (s , len );
921
+ PqCommBusy = false;
922
+ return res ;
923
+ }
924
+
925
+ static int
926
+ internal_putbytes (const char * s , size_t len )
888
927
{
889
928
size_t amount ;
890
929
891
930
while (len > 0 )
892
931
{
932
+ /* If buffer is full, then flush it out */
893
933
if (PqSendPointer >= PQ_BUFFER_SIZE )
894
- if (pq_flush ()) /* If buffer is full, then flush it out */
934
+ if (internal_flush ())
895
935
return EOF ;
896
936
amount = PQ_BUFFER_SIZE - PqSendPointer ;
897
937
if (amount > len )
@@ -912,6 +952,20 @@ pq_putbytes(const char *s, size_t len)
912
952
*/
913
953
int
914
954
pq_flush (void )
955
+ {
956
+ int res ;
957
+
958
+ /* No-op if reentrant call */
959
+ if (PqCommBusy )
960
+ return 0 ;
961
+ PqCommBusy = true;
962
+ res = internal_flush ();
963
+ PqCommBusy = false;
964
+ return res ;
965
+ }
966
+
967
+ static int
968
+ internal_flush (void )
915
969
{
916
970
static int last_reported_send_errno = 0 ;
917
971
@@ -988,26 +1042,40 @@ pq_flush(void)
988
1042
* then; dropping them is annoying, but at least they will still appear
989
1043
* in the postmaster log.)
990
1044
*
1045
+ * We also suppress messages generated while pqcomm.c is busy. This
1046
+ * avoids any possibility of messages being inserted within other
1047
+ * messages. The only known trouble case arises if SIGQUIT occurs
1048
+ * during a pqcomm.c routine --- quickdie() will try to send a warning
1049
+ * message, and the most reasonable approach seems to be to drop it.
1050
+ *
991
1051
* returns 0 if OK, EOF if trouble
992
1052
* --------------------------------
993
1053
*/
994
1054
int
995
1055
pq_putmessage (char msgtype , const char * s , size_t len )
996
1056
{
997
- if (DoingCopyOut )
1057
+ if (DoingCopyOut || PqCommBusy )
998
1058
return 0 ;
1059
+ PqCommBusy = true;
999
1060
if (msgtype )
1000
- if (pq_putbytes (& msgtype , 1 ))
1001
- return EOF ;
1061
+ if (internal_putbytes (& msgtype , 1 ))
1062
+ goto fail ;
1002
1063
if (PG_PROTOCOL_MAJOR (FrontendProtocol ) >= 3 )
1003
1064
{
1004
1065
uint32 n32 ;
1005
1066
1006
1067
n32 = htonl ((uint32 ) (len + 4 ));
1007
- if (pq_putbytes ((char * ) & n32 , 4 ))
1008
- return EOF ;
1068
+ if (internal_putbytes ((char * ) & n32 , 4 ))
1069
+ goto fail ;
1009
1070
}
1010
- return pq_putbytes (s , len );
1071
+ if (internal_putbytes (s , len ))
1072
+ goto fail ;
1073
+ PqCommBusy = false;
1074
+ return 0 ;
1075
+
1076
+ fail :
1077
+ PqCommBusy = false;
1078
+ return EOF ;
1011
1079
}
1012
1080
1013
1081
/* --------------------------------
@@ -1036,8 +1104,8 @@ pq_endcopyout(bool errorAbort)
1036
1104
{
1037
1105
if (!DoingCopyOut )
1038
1106
return ;
1039
- DoingCopyOut = false;
1040
1107
if (errorAbort )
1041
1108
pq_putbytes ("\n\n\\.\n" , 5 );
1042
1109
/* in non-error case, copy.c will have emitted the terminator line */
1110
+ DoingCopyOut = false;
1043
1111
}
0 commit comments