Re: Large stack causes WSAENOBUFS error
- From: Bruce Nairn <BruceNairn@xxxxxxxxxxxxxxxxxxxxxxxxx>
- Date: Tue, 29 Apr 2008 10:25:00 -0700
Thank you. This was very helpful. I didn't need the large stack for the
socket routine, but had missed increasing the stack for parallel threads.
Bruce
"RichK" wrote:
A default stack size of 855MB is exceptionally unreasonable for a process.
running in a 2GB address space.
That size allows at most 2 threads in a process.
I would guess that at some point, the socket call attempts to create an
additional thread using the default stack size.
If you actually need a thread with a super-large stack, you can always link
the process with a normal stack size, and explicitly create a thread with a
large stack size.
Using your test code you can replace main() with:
DWORD WINAPI largeStackThread(LPVOID p)
{
getConnection();
return 0;
}
int main(int argc, const char* argv[] ) {
int status;
HANDLE threadHandle;
DWORD threadId;
printf("start\n");
threadHandle=CreateThread(NULL,
0x34000000,
largeStackThread,
NULL,
STACK_SIZE_PARAM_IS_A_RESERVATION,
&threadId);
if (threadHandle!=NULL) {
WaitForSingleObject(threadHandle,INFINITE);
CloseHandle(threadHandle);
} else {
printf("Thread create failed with error status %d\n",GetLastError());
}
printf("finish\n");
return 0;
}
That way, the thread calling getConnection() still has a super-large stack,
but, the default thread stack size is not exceptionally large.
"Bruce Nairn" <BruceNairn@xxxxxxxxxxxxxxxxxxxxxxxxx> wrote in message
news:5971750D-8BEE-48AC-86E2-01CF741436BC@xxxxxxxxxxxxxxxx
Hi,
I started to get WSAENOBUFS errors from my code that uses the libpq
interface to PostgreSQL, and isolated the following problem. Can someone
explain what is going on and if there is a solution?
It seems that when a nonblocking socket connection is requested when the
application has a large stack (> ~855MB) a WSAENOBUFS error is returned
instead of the expected WSAEWOULDBLOCK. The expected behaviour occurs for
smaller stack sizes (< ~850 MB) and for blocking sockets. There is only
one
socket connection being requested and I don't see why there should be a
memory limitation. I got the same result on a couple of machines (all Win
XP
SP2) with different amounts of physical memory.
Any help would be appreciated.
Bruce
#include <stdio.h>
#include <cstdio>
#include <string>
#include <iostream>
#include "winsock2.h"
#include <ws2tcpip.h>
/* ---------------------
* This is a test program to demonstrate problem connecting to a
PostgreSQL
* database when the stack is set to exceed approx 0x32cd0000
* (decimal: 852295680) seems to depend slightly on shell environment
*
* code should return error code 10035: WSAEWOULDBLOCK Resource
temporarily unavailable.
* since this is a nonblocking socket and some time must elapse for the
connection to be established.
* for large stacks, returns error code 10055: WSAENOBUFS No buffer
space
available
*
* Compile on Windows XP with MS Visual Studio 2005:
* > cl /EHsc /F0x33000000 testconn5.cpp /link ws2_32.lib
*
* gives:
*
* >testconn5
* start
* WSADATA: 257 514 WinSock 2.0 Running 32767 65467
* socket 1948 2 1 0
* setsocketopt 0
* ioctlsocket 0 0
* PQconnectPoll: connect 1948 2448120 16
* PQconnectPoll: connect SOCK_ERRNO: 10055
* finish
*
* while compiling with a smaller stack (/F0x32000000 or smaller, or
omit),
gives expected output:
* > cl /EHsc /F0x32000000 testconn5.cpp /link ws2_32.lib
*
* >testconn5
* start
* WSADATA: 257 514 WinSock 2.0 Running 32767 65467
* socket 1948 2 1 0
* setsocketopt 0
* ioctlsocket 0 0
* PQconnectPoll: connect 1948 2448120 16
* PQconnectPoll: connect SOCK_ERRNO: 10035
* finish
*
* Is there a solution to allow this to work with a program that
requires
* a stack this large?
*/
// cl /EHsc /F0x33000000 testconn5.cpp /link ws2_32.lib
using namespace std;
void getConnection(){
char portstr[128];
struct addrinfo *addrs = NULL;
struct addrinfo hint;
const char *node;
int rc, ret;
SOCKET ConnectSocket;
int error_no;
u_long ioctlsocket_ret = 1;
char on = 1;
//----------------------
// Initialize Winsock
WSADATA wsaData;
int iResult = WSAStartup(MAKEWORD(1,1), &wsaData);
// postgresql uses winsock 1.1, using winsock 2.2 doesn't make a
difference
// int iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != NO_ERROR)
printf("Error at WSAStartup()\n");
printf ("WSADATA: %d %d %s %s %d %d\n", wsaData.wVersion,
wsaData.wHighVersion, wsaData.szDescription, wsaData.szSystemStatus,
wsaData.iMaxSockets, wsaData.iMaxUdpDg);
//----------------------
// Create a SOCKET for connecting to server
// proto = 0; //IPPROTO_TCP
// ConnectSocket = socket(AF_INET, SOCK_STREAM, 0);
ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (ConnectSocket == INVALID_SOCKET) {
printf("Error at socket(): %ld\n", WSAGetLastError());
WSACleanup();
return;
}
printf ("socket %d %d %d %d\n", ConnectSocket, AF_INET, SOCK_STREAM,
IPPROTO_TCP);
//----------------------
// The sockaddr_in structure specifies the address family,
// IP address, and port of the server to be connected to.
/*
* Determine the parameters to pass to pg_getaddrinfo_all.
*/
/* Initialize hint structure */
memset(&hint, 0, sizeof(hint));
hint.ai_socktype = SOCK_STREAM;
hint.ai_family = AF_UNSPEC;
/* Set up port number as a string */
_snprintf(portstr, sizeof(portstr), "%d", 5432);
hint.ai_family = AF_UNSPEC;
rc = getaddrinfo("localhost", portstr, &hint, &addrs);
//----------------------
// Postgresql uses nonblocking sockets, set option
iResult = setsockopt(ConnectSocket, IPPROTO_TCP, TCP_NODELAY, (char *)
&on,
sizeof(on));
printf ("setsocketopt %d\n", iResult);
/* Returns non-0 on failure, while fcntl() returns -1 on failure */
iResult = ioctlsocket(ConnectSocket, FIONBIO, &ioctlsocket_ret);
printf ("ioctlsocket %d %d\n", iResult, WSAGetLastError());
//----------------------
// Connect to server.
ret = connect(ConnectSocket, addrs->ai_addr,addrs->ai_addrlen);
printf ("PQconnectPoll: connect %d %d %d\n", ConnectSocket,
addrs->ai_addr,
addrs->ai_addrlen);
error_no = WSAGetLastError();
printf ("PQconnectPoll: connect SOCK_ERRNO: %d\n", error_no);
/* if successful: WSAGetLastError() should return error code 10035:
WSAEWOULDBLOCK Resource temporarily unavailable.
since this is a nonblocking socket and some time must elapse for the
connection to be established.
unsuccessful: WSAGetLastError() returns error code 10055:
WSAENOBUFS No buffer space available
*/
WSACleanup();
return;
}
int main(int argc, const char* argv[] ) {
int status;
cout << "start\n";
getConnection();
cout << "finish\n";
}
- References:
- Large stack causes WSAENOBUFS error
- From: Bruce Nairn
- Re: Large stack causes WSAENOBUFS error
- From: RichK
- Large stack causes WSAENOBUFS error
- Prev by Date: Re: Large stack causes WSAENOBUFS error
- Next by Date: Re: Receiving multiple UDP packets at once / UDP socket hangs
- Previous by thread: Re: Large stack causes WSAENOBUFS error
- Index(es):
Relevant Pages
|