6
6
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
7
7
*
8
8
* IDENTIFICATION
9
- * $PostgreSQL: pgsql/src/backend/port/win32/socket.c,v 1.13 2006/10/04 00:29:56 momjian Exp $
9
+ * $PostgreSQL: pgsql/src/backend/port/win32/socket.c,v 1.14 2006/10/13 13:59:47 teodor Exp $
10
10
*
11
11
*-------------------------------------------------------------------------
12
12
*/
@@ -102,11 +102,23 @@ pgwin32_poll_signals(void)
102
102
return 0 ;
103
103
}
104
104
105
+ static int
106
+ isDataGram (SOCKET s ) {
107
+ int type ;
108
+ int typelen = sizeof (type );
109
+
110
+ if ( getsockopt (s , SOL_SOCKET , SO_TYPE , (char * )& type , & typelen ) )
111
+ return 1 ;
112
+
113
+ return ( type == SOCK_DGRAM ) ? 1 : 0 ;
114
+ }
115
+
105
116
int
106
117
pgwin32_waitforsinglesocket (SOCKET s , int what )
107
118
{
108
119
static HANDLE waitevent = INVALID_HANDLE_VALUE ;
109
120
static SOCKET current_socket = -1 ;
121
+ static int isUDP = 0 ;
110
122
HANDLE events [2 ];
111
123
int r ;
112
124
@@ -127,8 +139,12 @@ pgwin32_waitforsinglesocket(SOCKET s, int what)
127
139
* socket from a previous call
128
140
*/
129
141
130
- if (current_socket != s && current_socket != -1 )
131
- WSAEventSelect (current_socket , waitevent , 0 );
142
+ if (current_socket != s )
143
+ {
144
+ if ( current_socket != -1 )
145
+ WSAEventSelect (current_socket , waitevent , 0 );
146
+ isUDP = isDataGram (s );
147
+ }
132
148
133
149
current_socket = s ;
134
150
@@ -140,7 +156,46 @@ pgwin32_waitforsinglesocket(SOCKET s, int what)
140
156
141
157
events [0 ] = pgwin32_signal_event ;
142
158
events [1 ] = waitevent ;
143
- r = WaitForMultipleObjectsEx (2 , events , FALSE, INFINITE , TRUE);
159
+
160
+ /*
161
+ * Just a workaround of unknown locking problem with writing
162
+ * in UDP socket under high load:
163
+ * Client's pgsql backend sleeps infinitely in
164
+ * WaitForMultipleObjectsEx, pgstat process sleeps in
165
+ * pgwin32_select(). So, we will wait with small
166
+ * timeout(0.1 sec) and if sockect is still blocked,
167
+ * try WSASend (see comments in pgwin32_select) and wait again.
168
+ */
169
+ if ((what & FD_WRITE ) && isUDP )
170
+ {
171
+ for (;;)
172
+ {
173
+ r = WaitForMultipleObjectsEx (2 , events , FALSE, 100 , TRUE);
174
+
175
+ if ( r == WAIT_TIMEOUT )
176
+ {
177
+ char c ;
178
+ WSABUF buf ;
179
+ DWORD sent ;
180
+
181
+ buf .buf = & c ;
182
+ buf .len = 0 ;
183
+
184
+ r = WSASend (s , & buf , 1 , & sent , 0 , NULL , NULL );
185
+ if (r == 0 ) /* Completed - means things are fine! */
186
+ return 1 ;
187
+ else if ( WSAGetLastError () != WSAEWOULDBLOCK )
188
+ {
189
+ TranslateSocketError ();
190
+ return 0 ;
191
+ }
192
+ }
193
+ else
194
+ break ;
195
+ }
196
+ }
197
+ else
198
+ r = WaitForMultipleObjectsEx (2 , events , FALSE, INFINITE , TRUE);
144
199
145
200
if (r == WAIT_OBJECT_0 || r == WAIT_IO_COMPLETION )
146
201
{
@@ -280,30 +335,31 @@ pgwin32_send(SOCKET s, char *buf, int len, int flags)
280
335
wbuf .len = len ;
281
336
wbuf .buf = buf ;
282
337
283
- r = WSASend (s , & wbuf , 1 , & b , flags , NULL , NULL );
284
- if (r != SOCKET_ERROR && b > 0 )
285
- /* Write succeeded right away */
286
- return b ;
287
-
288
- if (r == SOCKET_ERROR &&
289
- WSAGetLastError () != WSAEWOULDBLOCK )
290
- {
291
- TranslateSocketError ();
292
- return -1 ;
293
- }
294
-
295
- /* No error, zero bytes (win2000+) or error+WSAEWOULDBLOCK (<=nt4) */
338
+ /*
339
+ * Readiness of socket to send data to UDP socket
340
+ * may be not true: socket can become busy again! So loop
341
+ * until send or error occurs.
342
+ */
343
+ for (;;) {
344
+ r = WSASend (s , & wbuf , 1 , & b , flags , NULL , NULL );
345
+ if (r != SOCKET_ERROR && b > 0 )
346
+ /* Write succeeded right away */
347
+ return b ;
348
+
349
+ if (r == SOCKET_ERROR &&
350
+ WSAGetLastError () != WSAEWOULDBLOCK )
351
+ {
352
+ TranslateSocketError ();
353
+ return -1 ;
354
+ }
296
355
297
- if (pgwin32_waitforsinglesocket (s , FD_WRITE | FD_CLOSE ) == 0 )
298
- return -1 ;
356
+ /* No error, zero bytes (win2000+) or error+WSAEWOULDBLOCK (<=nt4) */
299
357
300
- r = WSASend (s , & wbuf , 1 , & b , flags , NULL , NULL );
301
- if (r == SOCKET_ERROR )
302
- {
303
- TranslateSocketError ();
304
- return -1 ;
358
+ if (pgwin32_waitforsinglesocket (s , FD_WRITE | FD_CLOSE ) == 0 )
359
+ return -1 ;
305
360
}
306
- return b ;
361
+
362
+ return -1 ;
307
363
}
308
364
309
365
0 commit comments