This is the mail archive of the
ecos-discuss@sourceware.org
mailing list for the eCos project.
Re: Socket leak when accept() is aborted by TCP RST?
On 2010-07-28, Andrew Lunn <andrew@lunn.ch> wrote:
> On Wed, Jul 28, 2010 at 07:56:41PM +0000, Grant Edwards wrote:
>> On 2010-07-28, Grant Edwards <grant.b.edwards@gmail.com> wrote:
>> > On 2010-07-27, Grant Edwards <grant.b.edwards@gmail.com> wrote:
>> >
>> >> I'm seeing what appears to me to be a socket leak in the accept()
>> >> operation provided by the "new" BSD network stack.
>> >
>> > The stack is definitely leaking sockets. I can now reliably reproduce
>> > the problem by opening a TCP connection and then immediately causing a
>> > TCP reset.
>>
>> AFAICT, the leak occurs in kern/sockio.c in bsd_accept():
>
> This makes sense. This is eCos code, not code taken directly from
> FreeBSD.
>
>> When an error is returned, the accept() function in
>> io/fileio//socket.cxx frees the file pointer and file descriptor but
>> not the socket:
>
> I would not expect it to. It does not know anything about sockets,
> they are internal to the stack.
>
>> So, nowhere does the socket get freed.
>
>> Where should the socket be freed? In bsd_accept() where it is removed
>> from the queue? Or in socket.cxx when the fd/fp are freed?
>
> I would say in bsd_accept(). However, it would be good to find the
> FreeBSD code equivalent of this code and see where it frees the
> socket.
I'm not sure, but I think it was done by the call to fdrop() that's
#if'ed out with a // FIXME comment in the eCos version:
1 //==========================================================================
2 //
3 // src/sys/kern/sockio.c
[...]
289 static int
290 bsd_accept(cyg_file *fp, cyg_file *new_fp,
291 struct sockaddr *name, socklen_t *anamelen)
292 {
[...]
413 noconnection:
414
415 #if 0 // FIXME
416 /*
417 * close the new descriptor, assuming someone hasn't ripped it
418 * out from under us.
419 */
420 if (error) {
421 if (fdp->fd_ofiles[fd] == nfp) {
422 fdp->fd_ofiles[fd] = NULL;
423 fdrop(nfp, p);
424 }
425 }
426 splx(s);
427
428 /*
429 * Release explicitly held references before returning.
430 */
431 done:
432 if (nfp != NULL)
433 fdrop(nfp, p);
434 fdrop(lfp, p);
435 return (error);
436 m_freem(nam);
437 #else
438 done:
439 splx(s);
440 if (sa)
441 FREE(sa, M_SONAME);
442 #endif
443
444 return (error);
445 }
In recent versions of FreeBSD, the fdrop() call appears to have been
replace by a call to fdclose() which in turn calls fdrop().
I'm 90% convinced that it should be done before the done: label at
line 438, but I haven't yet figured out how to do it. Neither
sofree(so) nor soclose(so) seem to have any effect. Perhaps there's a
reference count somewhere I have to decrement?
--
Grant Edwards grant.b.edwards Yow! Is it NOUVELLE
at CUISINE when 3 olives are
gmail.com struggling with a scallop
in a plate of SAUCE MORNAY?
--
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss