[En-Nut-Discussion] File descriptor leak in 4.8.7

Stefan Hax stefan at escherlogic.com
Wed May 6 16:07:15 CEST 2015


You don't seem to be doing anything for a non-0 return from 
NutTcpAccept().  Try something simple like:
while(NutTcpAccept(sock, 80));

since NutTcpAccept calls NutTcpStatePassiveOpenEvent etc.. follow the code..

Stefan.

On 2015-05-06 9:14 AM, Coleman Brumley wrote:
> Hi Henrik,
>
> That's originally what I was thinking and why I restructured the code
> differently from the example, so I knew that the call to being made to
> NutTcpCloseSocket explicitly. Here's my updated HTTP thread code. It does
> close the socket if the stream returned from _fdopen is NULL. Since adding
> the mutex, _fdopen no longer fails at all.
>
> THREAD(Service, arg)
> {
>      TCPSOCKET *sock;
>      FILE *stream;
>      u_char id = (u_char) ((uptr_t) arg);
>      u_char timeout=0;
>      u_long ul = 1000;
>      time_t t;
>      struct _tm tmx ;
>     uint16_t lowheapcounter=1000;
>      NutThreadSetPriority(72);	
>
>
>      /*
>       * Now loop endless for connections.
>       */
>
>      for (;;) {
>
>          /*
>           * Create a socket.
>           */
> 	if ((sock = NutTcpCreateSocket()) == 0)
> 	{
> 		printf("[%u] Creating socket failed\n", id);
> 		NutSleep(5000);
> 		continue;
> 	}
> 	NutTcpSetSockOpt (sock, SO_SNDTIMEO, &ul, sizeof(ul));
> 	NutTcpSetSockOpt(sock, SO_RCVTIMEO, &ul, sizeof(ul));
>          /*
>           * Listen on port 80. This call will block until we get a connection
>           * from a client.
>           */
>
> #ifdef REL_VERSION
>          NutTcpAccept(sock, 80);
> #else
>          NutTcpAccept(sock, 8080);
>
> #endif
> 	NutMutexLock(&httpSessionMutex);
>          /*
>           * Wait until at least 4 kByte of free RAM is available. This will
>           * keep the client connected in low memory situations.
>           */
> 		while (NutHeapAvailable() < 4096) {
> 			t=time(0l);
> 			localtime_r(&t,&tmx);
> 			printf("%02d:%02d:%02d %02d-%02d-%04d -- ",
> 				tmx.tm_hour,
> 				tmx.tm_min,
> 				tmx.tm_sec,
> 				tmx.tm_mon+1,
> 				tmx.tm_mday,
> 				tmx.tm_year+1900);
> 			printf("[%u] Low mem (%d)\n", id,
> (int)NutHeapAvailable());
> 			NutSleep(1000);
> 			lowheapcounter--;
> 			if(lowheapcounter<=0) Hreset();
> 		}
>
>          /*
>           * Associate a stream with the socket so we can use standard I/O
> calls.
>           */
> 		
> 		while (((stream = _fdopen((int) ((uptr_t) sock), "r+b")) ==
> 0)&&(++timeout<0xFF))
> 		{
>             			 NutSleep(10);
> 		}
> 		if(!stream)
> 		{
> 			printf("\n[%u] Creating stream device failed w/
> errno:%d\n", id,errno);
> 			NutTcpCloseSocket(sock);
> 			NutMutexUnlock(&httpSessionMutex);
> 			continue;
> 		}
> 		else
> 		{
> 		            NutHttpProcessRequest(stream);
> 		            fclose(stream);
> 		           NutTcpCloseSocket(sock);
> 		          NutMutexUnlock(&httpSessionMutex);
>          		}
>      	}
> }
> Coleman
>
>> -----Original Message-----
>> From: Henrik Maier [mailto:hmnews at proconx.com]
>> Sent: Tuesday, May 05, 2015 8:05 PM
>> To: cbrumley at polarsoft.biz; Ethernut User Chat (English)
>> Subject: Re: [En-Nut-Discussion] File descriptor leak in 4.8.7
>>
>> Hi Coleman,
>>
>> Could the memory leak be caused by not closing the socket when _fdopen
>> fails?
>>
>> Henrik
>>
>>
>> On 5/05/2015 7:47 AM, Coleman Brumley wrote:
>>> After doing some arithmetic, it appears that each occurrence of
>>> "Creating stream device failed" causes a 1271 byte leak from heap
>>> space. Does that number ring a bell?
>>>
>>>
>>>
>>> I've re-verified that this does not happen unless a browser is making
>>> HTTP requests of the controller. If the controller is just "sitting
>>> there", there is no leak. I verify this via a printout of available
>>> heap space every 30 minutes. After running for 4 hours, there were no
>> leaks.
>>>
>>>
>>> While there is no set time between each occurrence, this does seem to
>>> happen about 5 times in 30 minutes.
>>>
>>>
>>>
>>> The errno value 23 means that too many files are open, correct?
>>> FOPEN_MAX is defined as 8, so is having six concurrent HTTP threads
>>> running too many? Is it possible that the use of multiple HTTP threads
>>> without using a mutex is causing the file open handles to corrupt
>>> somehow and therefore not be closed correctly?
>>>
>>>
>>>
>>> Coleman
>>>
>>>
>>>
>>> From: Coleman Brumley [mailto:cbrumley at polarsoft.biz]
>>> Sent: Monday, May 04, 2015 1:19 PM
>>> To: en-nut-discussion at egnite.de
>>> Subject: File descriptor leak in 4.8.7
>>>
>>>
>>>
>>> Everyone,
>>>
>>>
>>>
>>> I'm working with Nut/OS v4.8.7 (for many, many reasons, I CANNOT
>>> upgrade the core OS). The processor is an Atmel SAM7X256.
>>>
>>>
>>>
>>> I'm encountering a problem with the use of file descriptors in HTTP,
>>> and I believe the core effect is a resource leak.
>>>
>>>
>>>
>>> Here is my HTTP service code:
>>>
>>>
>>>
>>> THREAD(Service, arg)
>>>
>>> {
>>>
>>>          TCPSOCKET *sock;
>>>
>>>          FILE *stream;
>>>
>>>          u_char id = (u_char) ((uptr_t) arg);
>>>
>>>         u_char timeout=0;
>>>
>>>          time_t t;
>>>
>>>          struct _tm tmx ;
>>>
>>>          uint16_t lowheapcounter=1000;
>>>
>>> NutThreadSetPriority(72);
>>>
>>>
>>>
>>>       /*
>>>
>>>        * Now loop endless for connections.
>>>
>>>        */
>>>
>>>
>>>
>>>       for (;;) {
>>>
>>>
>>>
>>>           /*
>>>
>>>            * Create a socket.
>>>
>>>            */
>>>
>>>                 if ((sock = NutTcpCreateSocket()) == 0)
>>>
>>>                 {
>>>
>>>                        printf("[%u] Creating socket failed\n", id);
>>>
>>>                        NutSleep(5000);
>>>
>>>                        continue;
>>>
>>>                 }
>>>
>>>           /*
>>>
>>>            * Listen on port 80. This call will block until we get a
>>> connection
>>>
>>>            * from a client.
>>>
>>>            */
>>>
>>>           NutTcpAccept(sock, 80);
>>>
>>>
>>>
>>>
>>>
>>>           /*
>>>
>>>            * Detect low heap and if it happens for too long, reset.
>>>
>>>            *
>>>
>>>            */
>>>
>>>                 while (NutHeapAvailable() < 4096) {
>>>
>>>                        t=time(0l);
>>>
>>>                        localtime_r(&t,&tmx);
>>>
>>>                        printf("%02d:%02d:%02d %02d-%02d-%04d -- ",
>>>
>>>                              tmx.tm_hour,
>>>
>>>                              tmx.tm_min,
>>>
>>>                              tmx.tm_sec,
>>>
>>>                              tmx.tm_mon+1,
>>>
>>>                              tmx.tm_mday,
>>>
>>>                              tmx.tm_year+1900);
>>>
>>>                        printf("[%u] Low mem (%d)\n", id,
>>> (int)NutHeapAvailable());
>>>
>>>                        NutSleep(1000);
>>>
>>>                        lowheapcounter--;
>>>
>>>                        if(lowheapcounter<=0) Hreset();
>>>
>>>                 }
>>>
>>>
>>>
>>>           /*
>>>
>>>            * Associate a stream with the socket so we can use standard
>>> I/O calls.
>>>
>>>            */
>>>
>>>
>>>
>>>                 while (((stream = _fdopen((int) ((uptr_t) sock),
>>> "r+b")) ==
>>> 0)&&(++timeout<0xFF))
>>>
>>>                 {
>>>
>>>                        NutSleep(10);
>>>
>>>                 }
>>>
>>>                 if(!stream)
>>>
>>>                 {
>>>
>>>                        printf("\n[%u] Creating stream device failed w/
>>> errno:%d\n", id,errno);
>>>
>>> NutTcpCloseSocket(sock);
>>>
>>>                        continue;
>>>
>>>                 }
>>>
>>>                 else
>>>
>>>                 {
>>>
>>>                        NutHttpProcessRequest(stream);
>>>
>>>                        fclose(stream);
>>>
>>>                        NutTcpCloseSocket(sock);
>>>
>>>                 }
>>>
>>>       }
>>>
>>> }
>>>
>>>
>>>
>>> The console output shows all is normal initially, but after a while
> (approx.
>>> 765 seconds, initially after boot time) I start seeing"
>>>
>>>
>>>
>>> [3] Creating stream device failed w/ errno:23
>>>
>>>
>>>
>>> Where the number in braces is the thread id. I'm running 6 HTTP
>>> threads, started as follows:
>>>
>>> for (i = 1; i <= 6; i++)
>>>
>>> {
>>>
>>> char thname[] = "httpd0";
>>>
>>>           thname[5] = '0' + i;
>>>
>>>           NutThreadCreate(thname, Service, (void *) (uptr_t)
>>> i,HTTPD_SERVICE_STACK);
>>>
>>> }
>>>
>>>
>>>
>>> The stack size is defined as 1024.
>>>
>>>
>>>
>>> I noticed this question was asked some time ago on this list, but I
>>> could not determine if there was ever a solution posted. There are
>>> other I/O processes running in the controller, but it ONLY runs low on
>>> resources when a browser is connected to it.
>>>
>>>
>>>
>>> Does anyone have any suggestions as to what I could look into as to
>>> what might be the problem?
>>>
>>>
>>>
>>> While the browser(s) are connected, the system appears to lose about
>>> 4.5k of heap space per 30 minutes!
>>>
>>>
>>>
>>> Thanks in advance.
>>>
>>>
>>>
>>> Best Regards,
>>>
>>> Coleman
>>>
>>> _______________________________________________
>>> http://lists.egnite.de/mailman/listinfo/en-nut-discussion
>>>
>
> _______________________________________________
> http://lists.egnite.de/mailman/listinfo/en-nut-discussion



More information about the En-Nut-Discussion mailing list