[SIGAR-127] use KERN_ARGMAX for KERN_PROCARGS2 buffer size

This commit is contained in:
Doug MacEachern 2008-10-15 02:53:23 +00:00
parent f7098e2c5b
commit 0d3be12ac6
2 changed files with 48 additions and 15 deletions

View File

@ -252,7 +252,7 @@ int sigar_os_open(sigar_t **sigar)
(*sigar)->ncpu = ncpu; (*sigar)->ncpu = ncpu;
(*sigar)->lcpu = -1; (*sigar)->lcpu = -1;
(*sigar)->argmax = 0;
(*sigar)->boot_time = boottime.tv_sec; /* XXX seems off a bit */ (*sigar)->boot_time = boottime.tv_sec; /* XXX seems off a bit */
(*sigar)->pagesize = getpagesize(); (*sigar)->pagesize = getpagesize();
@ -294,6 +294,25 @@ char *sigar_os_error_string(sigar_t *sigar, int err)
} }
} }
/* ARG_MAX in FreeBSD 6.0 == 262144, which blows up the stack */
#define SIGAR_ARG_MAX 65536
static size_t sigar_argmax_get(sigar_t *sigar)
{
#ifdef KERN_ARGMAX
int mib[] = { CTL_KERN, KERN_ARGMAX };
size_t size = sizeof(sigar->argmax);
if (sigar->argmax != 0) {
return sigar->argmax;
}
if (sysctl(mib, NMIB(mib), &sigar->argmax, &size, NULL, 0) == 0) {
return sigar->argmax;
}
#endif
return SIGAR_ARG_MAX;
}
#if defined(DARWIN) #if defined(DARWIN)
static int sigar_vmstat(sigar_t *sigar, vm_statistics_data_t *vmstat) static int sigar_vmstat(sigar_t *sigar, vm_statistics_data_t *vmstat)
{ {
@ -1384,12 +1403,21 @@ int sigar_proc_state_get(sigar_t *sigar, sigar_pid_t pid,
#if defined(DARWIN) #if defined(DARWIN)
typedef struct { typedef struct {
char buffer[8096], *ptr, *end; char *buf, *ptr, *end;
int count; int count;
} sigar_kern_proc_args_t; } sigar_kern_proc_args_t;
static void sigar_kern_proc_args_destroy(sigar_kern_proc_args_t *kargs)
{
if (kargs->buf) {
free(kargs->buf);
kargs->buf = NULL;
}
}
/* re-usable hack for use by proc_args and proc_env */ /* re-usable hack for use by proc_args and proc_env */
static int sigar_kern_proc_args_get(sigar_pid_t pid, static int sigar_kern_proc_args_get(sigar_t *sigar,
sigar_pid_t pid,
char *exe, char *exe,
sigar_kern_proc_args_t *kargs) sigar_kern_proc_args_t *kargs)
{ {
@ -1398,21 +1426,23 @@ static int sigar_kern_proc_args_get(sigar_pid_t pid,
* http://darwinsource.opendarwin.org/10.4.1/adv_cmds-79.1/ps.tproj/print.c * http://darwinsource.opendarwin.org/10.4.1/adv_cmds-79.1/ps.tproj/print.c
*/ */
int mib[3], len; int mib[3], len;
size_t size = sizeof(kargs->buffer); size_t size = sigar_argmax_get(sigar);
char *args = kargs->buffer;
kargs->buf = malloc(size);
mib[0] = CTL_KERN; mib[0] = CTL_KERN;
mib[1] = KERN_PROCARGS2; mib[1] = KERN_PROCARGS2;
mib[2] = pid; mib[2] = pid;
if (sysctl(mib, NMIB(mib), args, &size, NULL, 0) < 0) { if (sysctl(mib, NMIB(mib), kargs->buf, &size, NULL, 0) < 0) {
sigar_kern_proc_args_destroy(kargs);
return errno; return errno;
} }
kargs->end = &args[size]; kargs->end = &kargs->buf[size];
memcpy(&kargs->count, args, sizeof(kargs->count)); memcpy(&kargs->count, kargs->buf, sizeof(kargs->count));
kargs->ptr = args + sizeof(kargs->count); kargs->ptr = kargs->buf + sizeof(kargs->count);
len = strlen(kargs->ptr); len = strlen(kargs->ptr);
if (exe) { if (exe) {
@ -1421,6 +1451,7 @@ static int sigar_kern_proc_args_get(sigar_pid_t pid,
kargs->ptr += len+1; kargs->ptr += len+1;
if (kargs->ptr == kargs->end) { if (kargs->ptr == kargs->end) {
sigar_kern_proc_args_destroy(kargs);
return exe ? SIGAR_OK : ENOENT; return exe ? SIGAR_OK : ENOENT;
} }
@ -1431,6 +1462,7 @@ static int sigar_kern_proc_args_get(sigar_pid_t pid,
} }
if (kargs->ptr == kargs->end) { if (kargs->ptr == kargs->end) {
sigar_kern_proc_args_destroy(kargs);
return exe ? SIGAR_OK : ENOENT; return exe ? SIGAR_OK : ENOENT;
} }
@ -1462,9 +1494,6 @@ static int kern_proc_args_skip_argv(sigar_kern_proc_args_t *kargs)
} }
#endif #endif
/* ARG_MAX in FreeBSD 6.0 == 262144, which blows up the stack */
#define SIGAR_ARG_MAX 65536
int sigar_os_proc_args_get(sigar_t *sigar, sigar_pid_t pid, int sigar_os_proc_args_get(sigar_t *sigar, sigar_pid_t pid,
sigar_proc_args_t *procargs) sigar_proc_args_t *procargs)
{ {
@ -1473,7 +1502,7 @@ int sigar_os_proc_args_get(sigar_t *sigar, sigar_pid_t pid,
sigar_kern_proc_args_t kargs; sigar_kern_proc_args_t kargs;
char *ptr, *end; char *ptr, *end;
status = sigar_kern_proc_args_get(pid, NULL, &kargs); status = sigar_kern_proc_args_get(sigar, pid, NULL, &kargs);
if (status != SIGAR_OK) { if (status != SIGAR_OK) {
return status; return status;
} }
@ -1509,6 +1538,7 @@ int sigar_os_proc_args_get(sigar_t *sigar, sigar_pid_t pid,
ptr += alen; ptr += alen;
} }
sigar_kern_proc_args_destroy(&kargs);
return SIGAR_OK; return SIGAR_OK;
#elif defined(__FreeBSD__) || defined(__NetBSD__) #elif defined(__FreeBSD__) || defined(__NetBSD__)
char buffer[SIGAR_ARG_MAX+1], *ptr=buffer; char buffer[SIGAR_ARG_MAX+1], *ptr=buffer;
@ -1587,13 +1617,14 @@ int sigar_proc_env_get(sigar_t *sigar, sigar_pid_t pid,
sigar_kern_proc_args_t kargs; sigar_kern_proc_args_t kargs;
char *ptr, *end; char *ptr, *end;
status = sigar_kern_proc_args_get(pid, NULL, &kargs); status = sigar_kern_proc_args_get(sigar, pid, NULL, &kargs);
if (status != SIGAR_OK) { if (status != SIGAR_OK) {
return status; return status;
} }
status = kern_proc_args_skip_argv(&kargs); status = kern_proc_args_skip_argv(&kargs);
if (status != SIGAR_OK) { if (status != SIGAR_OK) {
sigar_kern_proc_args_destroy(&kargs);
return status; return status;
} }
@ -1633,6 +1664,7 @@ int sigar_proc_env_get(sigar_t *sigar, sigar_pid_t pid,
} }
} }
sigar_kern_proc_args_destroy(&kargs);
return SIGAR_OK; return SIGAR_OK;
#else #else
char **env; char **env;
@ -1747,7 +1779,7 @@ int sigar_proc_exe_get(sigar_t *sigar, sigar_pid_t pid,
int status; int status;
sigar_kern_proc_args_t kargs; sigar_kern_proc_args_t kargs;
status = sigar_kern_proc_args_get(pid, procexe->name, &kargs); status = sigar_kern_proc_args_get(sigar, pid, procexe->name, &kargs);
if (status != SIGAR_OK) { if (status != SIGAR_OK) {
return status; return status;
} }

View File

@ -60,6 +60,7 @@ struct sigar_t {
sigar_pid_t last_pid; sigar_pid_t last_pid;
bsd_pinfo_t *pinfo; bsd_pinfo_t *pinfo;
int lcpu; int lcpu;
size_t argmax;
#ifdef DARWIN #ifdef DARWIN
mach_port_t mach_port; mach_port_t mach_port;
# ifdef DARWIN_HAS_LIBPROC_H # ifdef DARWIN_HAS_LIBPROC_H