Re: Large stack causes WSAENOBUFS error



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";
}






.



Relevant Pages

  • Large stack causes WSAENOBUFS error
    ... I started to get WSAENOBUFS errors from my code that uses the libpq ... It seems that when a nonblocking socket connection is requested when the ... smaller stack sizes and for blocking sockets. ...
    (microsoft.public.win32.programmer.networks)
  • Re: Large stack causes WSAENOBUFS error
    ... A default stack size of 855MB is exceptionally unreasonable for a process ... int main{ ... It seems that when a nonblocking socket connection is requested when the ...
    (microsoft.public.win32.programmer.networks)
  • Re: TCP buffer splitting question ?
    ... > The Send at the client side always return the same size that I asked for, ... Why the receive socket does not buffer as I ... segments and push them up the stack to your application, ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: C# Raw Socket Issues starting TCP Connections
    ... the TCP stack has no information about what you are doing ... of IP packet and send it along with the data, you can build a SYN packet ... and send it to the TCP server program which is actively listening. ... > read incomming data if I use IOControl and set the socket SIO_RCVALL. ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: socket()
    ... of Tcp/Ip network use in Unix. ... The socket call causes ... binding activates the listener on a specific port. ... Socket call fills a struct in the stack and provides ...
    (microsoft.public.windows.server.security)

Quantcast