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, Grant Edwards <grant.b.edwards@gmail.com> wrote:
> On 2010-07-28, Andrew Lunn <andrew@lunn.ch> wrote:
>>> 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?
setting the SS_NOFDREF so_state flag before calling sofree() seems to
work.
Is there some reason we need to keep the above code that's elided by
the #if 0?
While looking at the rest of that same function, I noticed another
block of #if'ed out code with a // FIXME comment.
Does anybody know what it is that needs fixing below?
334 /*
335 * At this point we know that there is at least one connection
336 * ready to be accepted. Remove it from the queue prior to
337 * allocating the file descriptor for it since falloc() may
338 * block allowing another process to accept the connection
339 * instead.
340 */
341 so = TAILQ_FIRST(&head->so_comp);
342 TAILQ_REMOVE(&head->so_comp, so, so_list);
343 head->so_qlen--;
344
345 #if 0 // FIXME
346 fflag = lfp->f_flag;
347 error = falloc(p, &nfp, &fd);
348 if (error) {
349 /*
350 * Probably ran out of file descriptors. Put the
351 * unaccepted connection back onto the queue and
352 * do another wakeup so some other process might
353 * have a chance at it.
354 */
355 TAILQ_INSERT_HEAD(&head->so_comp, so, so_list);
356 head->so_qlen++;
357 wakeup_one(&head->so_timeo);
358 splx(s);
359 goto done;
360 }
361 fhold(nfp);
362 p->p_retval[0] = fd;
363
364 /* connection has been removed from the listen queue */
365 KNOTE(&head->so_rcv.sb_sel.si_note, 0);
366 #endif
367
368 so->so_state &= ~SS_COMP;
369 so->so_head = NULL;
--
Grant Edwards grant.b.edwards Yow! I have seen these EGG
at EXTENDERS in my Supermarket
gmail.com ... I have read the
INSTRUCTIONS ...
--
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss