This is the mail archive of the ecos-discuss@sourceware.org mailing list for the eCos project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]