[En-Nut-Discussion] _fdopen failed to create the stream on the socket
Ma-Prokop, Yuhong
yuhong.ma.prokop at ims.fraunhofer.de
Wed Nov 11 09:17:36 CET 2009
Hello Everyone,
I have one problem with my nut/os Webserver: after some calling from the
clients (browers) the webserver does not response any more!
I tried to track along the problem: it is because the _fdopen function
failed to create stream on the socket and returns "-1". According to my
debugging output the opened stream number is over the FOPEN_MAX which is
defined in nut/os.
But fclose function was called everytime after the successful _fdopen.
Then i found out that the fclose (as following) returns sometimes "255"
instead of "0" as it should be, so the existing stream cannot be closed,
then until the maximal streams are opened, no further clients-request
shall be processed!
Does somebody have the same problem with nut/os webserver?
Any help is appreciated!
Hong
my webserver thread is as following:
THREAD(Service, arg) {
FILE *http_stream;
TCPSOCKET *sock;
u_char id = (u_char) ((uptr_t) arg);
// give each thread a (unique) priority
NutThreadSetPriority( EHZ_HTTP_PRIO ); //+ id
/*
* Now loop endless for connections.
*/
for(;;)
{
/*
* Create a socket.
*
* May fail because of lacking ressources
*/
if ((sock = NutTcpCreateSocket()) == 0)
{
LOG_ERROR("%d: tcp socket create failed", id);
NutSleep(5000);
continue;
}
else
/*
* Set socket options.
*/
{
u_short mss = 1460;
u_short tcpbufsiz = 8760;
u_long tmo = 5000;
if (NutTcpSetSockOpt(sock, TCP_MAXSEG, &mss, sizeof(mss)))
LOG_ERROR("Sockopt MSS failed");
if (NutTcpSetSockOpt(sock, SO_RCVBUF, &tcpbufsiz,
sizeof(tcpbufsiz)))
LOG_ERROR("Sockopt rxbuf failed");
if (NutTcpSetSockOpt(sock, SO_RCVTIMEO, &tmo, sizeof(tmo)))
LOG_ERROR("Sockopt rx timeout failed");
}
/*
* Listen on port 80. This call will block until we get a
connection
* from a client.
*/
NutTcpAccept(sock, 80);
// printf("remote-ip: %s\r\n", inet_ntoa(sock->so_remote_addr));
/*
* Wait until at least 4 kByte of free RAM is available. This
will
* keep the client connected in low memory situations.
*/
while( NutHeapAvailable() < 4096 )
{
LOG_ERROR("%d: not enough memory!", id );
// reboot the device if the amount of memory is too
small
//****
RESET;
//****
NutSleep(1000);
}
/*
* Associate a stream with the socket so we can use standard I/O
calls.
*
* should not fail
*/
// inserting a timeout here was a tip of Piotr Szlachta in the
ethernut mailing list:
//
http://lists.egnite.de/pipermail/en-nut-discussion/2007-November/008655.
html
int timeout=0;
while ( !(http_stream = _fdopen((int) ((uptr_t) sock), "r+b"))
&& ++timeout<0xFF )
NutSleep (10);
if ((int)http_stream != 0 && (int) http_stream != -1 &&
(int)http_stream != -2) {
/*
* This API call saves us a lot of work. It will parse the
* client's HTTP request, send any requested file from the
* registered file system or handle CGI requests by calling
* our registered CGI routine.
*/
#ifndef USE_UROM_FOR_HTTP
if(!isMmcAccessGranted()) {
LOG_ERROR("Please check SD-Card.");
}
else {
NutHttpProcessRequest(http_stream);
}
#else
NutHttpProcessRequest(http_stream);
#endif
/*
* Destroy the virtual stream device.
*/
fclose_result = fclose(http_stream);
LOG_ERROR("INFO: fclose with stream: %d result: %d: \n",
http_stream, fclose_result);
}
else {
LOG_ERROR("DEFEKT with Thread %d: fdopen result: %d: \n",id,
(int)http_stream);
NutSleep(100);
}
/*
* Close our socket.
*/
if( (NutTcpCloseSocket(sock)) == -1)
LOG_ERROR("ACHTUNG: Socket not closed");
}
}
The _fdopen function in my nut/os:
(I modified the function just lightly to get know the failed reason)
FILE *_fdopen(int fd, CONST char *mode)
{
int mflags = _O_TEXT;
u_char i;
/*
* Translate file mode.
*/
if ((mflags = _fmode(mode)) == EOF)
return (FILE*)0;
/*
* Find an empty slot.
*/
for (i = 3; __iob[i]; i++)
if (i >= FOPEN_MAX - 1) {
errno = ENFILE;
// return 0;
return (FILE*)(-1);
}
if ((__iob[i] = malloc(sizeof(FILE))) != 0) {
__iob[i]->iob_fd = fd;
__iob[i]->iob_mode = mflags;
__iob[i]->iob_flags = 0;
__iob[i]->iob_unget = 0;
return __iob[i];
} else
{
errno = ENOMEM;
return (FILE*)(-2);
}
// return __iob[i];
}
The _fdopen function in my nut/os:
int fclose(FILE * stream)
{
int rc = EOF;
u_char i;
/*
* Search the list first to detect bad stream pointer.
*/
if (stream == 0) {
errno = EBADF;
return EOF;
}
for (i = 0; __iob[i] != stream;) {
if (++i >= FOPEN_MAX) {
errno = EBADF;
return EOF;
}
}
/*
* Ignore unopened standard streams.
*/
//if ((void *) stream < RAMSTART)
// return 0;
/*
* Close the file or device.
*/
if (_close(stream->iob_fd) == 0)
rc = 0;
free(stream);
__iob[i] = 0;
return rc;
}
More information about the En-Nut-Discussion
mailing list