Date: Wed, 3 Jun 1998 03:50:02 -0700 (PDT) From: Craig Metz <cmetz@inner.net> To: freebsd-bugs@FreeBSD.ORG Subject: Re: kern/6837: in_setpeeraddr() and in_setsockaddr() block on memory Message-ID: <199806031050.DAA21239@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
The following reply was made to PR kern/6837; it has been noted by GNATS. From: Craig Metz <cmetz@inner.net> To: dg@root.com Cc: freebsd-gnats-submit@FreeBSD.ORG Subject: Re: kern/6837: in_setpeeraddr() and in_setsockaddr() block on memory Date: Wed, 03 Jun 1998 06:37:39 -0300 In message <199806030337.UAA19868@implode.root.com>, you write: >>These two functions now MALLOC their address parameter inline rather >>than having the address buffer passed in. They do so with M_WAITOK, >>which will tsleep() the process indefinitely waiting for the memory. >>Granted, if you're that short on memory on a BSD system, you'll have >>bigger problems, but IMO these functions should kick ENOBUFS back up the >>stack and get out of kernel mode (thus freeing up some other buffer >>memory) rather than block the process. > > Why do you think it should be that way? It won't be an indefinate wait, >just a wait until memory is freed up which shouldn't be for very long. I guess it's a bit of a philosophical thing. If you return ENOBUFS, the app is able to choose what it does about not having enough memory to complete the operation. Most will quit, thus freeing up the memory associated with them and helping the global out-of-memory problem (even if kernel memory is a separate pool, there's almost always some kernel memory associated with the process). Some will back out transactions, or return a network failure, or sleep/spin for a while and then try again. But that way, a well-written app has the choice. If you do it M_WAIT style, the kernel tsleep()s the process, and the app doesn't have any choice. It sleeps, possibly for a long time. By the time it wakes up, given many typical places where getpeername()/getsockname() are used, the returned value will be irrelevant. Consider the case that so many people break^H^H^H^H^Hdesign their operating systems for these days, the web. WWW servers typically call getpeername() and getsockname() early in an incoming connection. If the call fails, the server can close the connection, freeing up some kernel memory, and the client will usually return an error. If the call sleeps, the connection will hang, and the client will simply retry. If I'm not mistaken, unless it's doing asynchronous I/O, the process won't be awakened by the connection close event, so it sits there until memory becomes available, holding some itself. Meanwhile, the client is firing off a new TCP connection and causing another getpeername()/ getsockname() call, which may be able to grab newly-freed memory before the first process can wake up. The other, far easier to explain answer, is that we're putting some code in there for IPv6 support that makes the malloc() happen at splnet(), and tsleep()ing at such a priority is not good. -Craig To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-bugs" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199806031050.DAA21239>