66 * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
77 *
88 * 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 $
1010 *
1111 *-------------------------------------------------------------------------
1212 */
@@ -102,11 +102,23 @@ pgwin32_poll_signals(void)
102102return 0 ;
103103}
104104
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+
105116int
106117pgwin32_waitforsinglesocket (SOCKET s ,int what )
107118{
108119static HANDLE waitevent = INVALID_HANDLE_VALUE ;
109120static SOCKET current_socket = -1 ;
121+ static int isUDP = 0 ;
110122HANDLE events [2 ];
111123int r ;
112124
@@ -127,8 +139,12 @@ pgwin32_waitforsinglesocket(SOCKET s, int what)
127139 * socket from a previous call
128140 */
129141
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+ }
132148
133149current_socket = s ;
134150
@@ -140,7 +156,46 @@ pgwin32_waitforsinglesocket(SOCKET s, int what)
140156
141157events [0 ]= pgwin32_signal_event ;
142158events [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);
144199
145200if (r == WAIT_OBJECT_0 || r == WAIT_IO_COMPLETION )
146201{
@@ -280,30 +335,31 @@ pgwin32_send(SOCKET s, char *buf, int len, int flags)
280335wbuf .len = len ;
281336wbuf .buf = buf ;
282337
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+ }
296355
297- if (pgwin32_waitforsinglesocket (s ,FD_WRITE |FD_CLOSE )== 0 )
298- return -1 ;
356+ /* No error, zero bytes (win2000+) or error+WSAEWOULDBLOCK (<=nt4) */
299357
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 ;
305360}
306- return b ;
361+
362+ return -1 ;
307363}
308364
309365