Date: Mon, 24 Feb 2014 13:09:24 +0900 (JST) From: Hiroki Sato <hrs@FreeBSD.org> To: ianf@clue.co.za Cc: current@FreeBSD.org Subject: Re: netstat: sysctl: net.route.0.0.dump.0: Cannot allocate memory Message-ID: <20140224.130924.1512809959333112659.hrs@allbsd.org> In-Reply-To: <E1WGmTE-0000nr-Us@clue.co.za> References: <E1WGkzK-0000gb-E2@clue.co.za> <E1WGltZ-0000kf-1A@clue.co.za> <E1WGmTE-0000nr-Us@clue.co.za>
next in thread | previous in thread | raw e-mail | index | archive | help
----Security_Multipart0(Mon_Feb_24_13_09_24_2014_476)-- Content-Type: Multipart/Mixed; boundary="--Next_Part(Mon_Feb_24_13_09_24_2014_200)--" Content-Transfer-Encoding: 7bit ----Next_Part(Mon_Feb_24_13_09_24_2014_200)-- Content-Type: Text/Plain; charset=us-ascii Content-Transfer-Encoding: 7bit Ian FREISLICH <ianf@clue.co.za> wrote in <E1WGmTE-0000nr-Us@clue.co.za>: ia> Hiroki Sato wrote: ia> > Hm, how about the attached one? ia> > ia> > I think the cause is just a race when length of the sysctl's output ia> > is changed in kernel after the buffer allocation in userspace, not ia> > memory shortage. Size of the routing table can quickly change. ia> ia> You are correct. It's growing at about 9000 entries per second (I ia> wish it were faster). ia> ia> This is what the output looks like now. I guess I'm not the average ia> case. Can you try the attached patch? It will attempt to enlarge the buffer every retry. -- Hiroki ----Next_Part(Mon_Feb_24_13_09_24_2014_200)-- Content-Type: Text/X-Patch; charset=us-ascii Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="netstat-2.diff" Index: route.c =================================================================== --- route.c (revision 262313) +++ route.c (working copy) @@ -69,6 +69,7 @@ #include <sysexits.h> #include <unistd.h> #include <err.h> +#include <errno.h> #include "netstat.h" #define kget(p, d) (kread((u_long)(p), (char *)&(d), sizeof (d))) @@ -560,7 +561,7 @@ char *buf, *next, *lim; struct rt_msghdr *rtm; struct sockaddr *sa; - int fam = 0, ifindex = 0, size; + int fam = 0, ifindex = 0, size, count = 0; struct ifaddrs *ifap, *ifa; struct sockaddr_dl *sdl; @@ -600,6 +601,7 @@ freeifaddrs(ifap); +retry: mib[0] = CTL_NET; mib[1] = PF_ROUTE; mib[2] = 0; @@ -607,19 +609,27 @@ mib[4] = NET_RT_DUMP; mib[5] = 0; mib[6] = fibnum; - if (sysctl(mib, 7, NULL, &needed, NULL, 0) < 0) { - err(1, "sysctl: net.route.0.%d.dump.%d estimate", af, fibnum); + if (sysctl(mib, nitems(mib), NULL, &needed, NULL, 0) < 0) + err(EX_OSERR, "sysctl: net.route.0.%d.dump.%d estimate", af, + fibnum); + needed += PAGE_SIZE * (count + 1); + if ((buf = malloc(needed)) == NULL) + errx(EX_OSERR, "malloc(%zd)", needed); + if (sysctl(mib, nitems(mib), buf, &needed, NULL, 0) < 0) { + if (errno == ENOMEM && count++ < 20) { + warnx("Routing table grew, retrying"); + sleep(1); + free(buf); + goto retry; + } else + err(EX_OSERR, "sysctl: net.route.0.%d.dump.%d", af, + fibnum); } - - if ((buf = malloc(needed)) == 0) { - errx(2, "malloc(%lu)", (unsigned long)needed); - } - if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) { - err(1, "sysctl: net.route.0.%d.dump.%d", af, fibnum); - } lim = buf + needed; for (next = buf; next < lim; next += rtm->rtm_msglen) { rtm = (struct rt_msghdr *)next; + if (rtm->rtm_version != RTM_VERSION) + continue; /* * Peek inside header to determine AF */ @@ -632,6 +642,7 @@ } p_rtentry_sysctl(rtm); } + free(buf); } static void ----Next_Part(Mon_Feb_24_13_09_24_2014_200)---- ----Security_Multipart0(Mon_Feb_24_13_09_24_2014_476)-- Content-Type: application/pgp-signature Content-Transfer-Encoding: 7bit -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iEYEABECAAYFAlMKxfQACgkQTyzT2CeTzy311gCcCe7gnRiQIX0bqSKt4ykC6hX/ EiIAoK2IhblmxU68fA+6Xbw/YiJ5w8U9 =+fo0 -----END PGP SIGNATURE----- ----Security_Multipart0(Mon_Feb_24_13_09_24_2014_476)----
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20140224.130924.1512809959333112659.hrs>