Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 47df6e7

Browse filesBrowse files
committed
Fix infinite sleep and failes of send in Win32.
1) pgwin32_waitforsinglesocket(): WaitForMultipleObjectsEx now called with finite timeout (100ms) in case of FP_WRITE and UDP socket. If timeout occurs then pgwin32_waitforsinglesocket() tries to write empty packet goes to WaitForMultipleObjectsEx again. 2) pgwin32_send(): add loop around WSASend and pgwin32_waitforsinglesocket(). The reason is: for overlapped socket, 'ok' result from pgwin32_waitforsinglesocket() isn't guarantee that socket is still free, it can become busy again and following WSASend call will fail with WSAEWOULDBLOCK error. See http://archives.postgresql.org/pgsql-hackers/2006-10/msg00561.php
1 parent efa0e86 commit 47df6e7
Copy full SHA for 47df6e7

File tree

Expand file treeCollapse file tree

1 file changed

+81
-25
lines changed
Filter options
Expand file treeCollapse file tree

1 file changed

+81
-25
lines changed

‎src/backend/port/win32/socket.c

Copy file name to clipboardExpand all lines: src/backend/port/win32/socket.c
+81-25Lines changed: 81 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
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)
102102
return 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+
105116
int
106117
pgwin32_waitforsinglesocket(SOCKET s, int what)
107118
{
108119
static HANDLE waitevent = INVALID_HANDLE_VALUE;
109120
static SOCKET current_socket = -1;
121+
static int isUDP = 0;
110122
HANDLE events[2];
111123
int 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

133149
current_socket = s;
134150

@@ -140,7 +156,46 @@ pgwin32_waitforsinglesocket(SOCKET s, int what)
140156

141157
events[0] = pgwin32_signal_event;
142158
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);
144199

145200
if (r == WAIT_OBJECT_0 || r == WAIT_IO_COMPLETION)
146201
{
@@ -280,30 +335,31 @@ pgwin32_send(SOCKET s, char *buf, int len, int flags)
280335
wbuf.len = len;
281336
wbuf.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

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.