Greetings list.
I'm trying to write a gmond module in C that will count the number of named
processes running on the host. The full sourcecode of the module is pasted
below.
The problem I'm running into is a segfault, which gdb says is occuring in
apr_array_push. The idea behind this module is that the user will provide a
space-separated list of process names as a value to a parameter called
"ProcessNames" in the config file (something similar to Value = "httpd jsvc
bash"). Since there's no way of knowing how many processes the user might
provide, I need to grow the metric definition array dynamically, and that's why
I'm calling apr_array_push. The module is segfaulting on my first call to
apr_array_push.
I must admit that I don't know anything about the apr, I'm mostly just
following mod_gstatus.c as an example, so I don't have a good mental picture of
the data structures here. I see that apr_array_push has to do with apr's
dynamic array functionality, but I must be using it wrong somehow. I was
hoping whatever I'm doing wrong might be glaringly obvious to someone on the
list. Any and all help is appreciated.
Thanks in advance.
-dave
################## mod_cprocs.c source ##################
/*******************************************************************************
* This software is public domain. No rights reserved. Do whatever you want
* (and leave me alone)
*
* Author: Dave Josephsen (dave at skeptech.org)
******************************************************************************/
#include <gm_metric.h>
#include <ganglia_priv.h>
#include <apr_strings.h>
#include <stdlib.h>
#include <stdio.h>
#include <strings.h>
#include <string.h>
#include <time.h>
#include <readproc.h> // the readproc library from the linux procps project.
most systems don't have this installed by default
extern mmodule cp_module;
static apr_array_header_t *metric_info = NULL;
char *processNames;
g_val_t count_procs(char *proc_name) {
//This function counts the number of instances of the given name (like 'httpd'
for example)
int numprocs=0;
PROCTAB *proct;
proc_t *proc_info;
g_val_t returnThis;
proct = openproc(PROC_FILLARG | PROC_FILLSTAT | PROC_FILLSTATUS);
while ((proc_info = readproc(proct,NULL))) {
if(!strncmp(proc_info->cmd,proc_name,sizeof(proc_info->cmd))){
numprocs++;
}
}
closeproc(proct);
returnThis.int32 = numprocs;
return returnThis;
}
static int cp_metric_init ( apr_pool_t *p )
{
const char* str_params = cp_module.module_params;
apr_array_header_t *list_params = cp_module.module_params_list;
mmparam *params;
char processNamesCp[4242];
Ganglia_25metric *gmi;
char processDesc[1024];
int i;
srand(time(NULL)%99);
/* Read the parameters from the gmond.conf file. */
if (list_params) {
debug_msg("[mod_countproc] Received following params list: ");
params = (mmparam*) list_params->elts;
for(i=0; i< list_params->nelts; i++) {
debug_msg("\tParam: %s = %s", params[i].name, params[i].value);
if (!strcasecmp(params[i].name, "ProcessNames")) {
processNames = params[i].value;
}
}
}
// metadata storage
strncpy(processNamesCp, processNames,sizeof(processNames)); //avoid
allowing strtok to clobber the original ProcessNames string
char * processName = strtok(processNamesCp, " ");
for(i=0; processName != NULL; i++) {
gmi = apr_array_push(metric_info);
snprintf(processDesc,sizeof(processDesc)-1,"Number of %s
Processes",processName);
processDesc[sizeof(processDesc)-1]='\x0';
/* gmi->key will be automatically assigned by gmond */
gmi->name = apr_pstrdup (p, processName);
gmi->tmax = 512;
gmi->type = GANGLIA_VALUE_UNSIGNED_INT;
gmi->units = apr_pstrdup(p, "count");
gmi->slope = apr_pstrdup(p, "both");
gmi->fmt = apr_pstrdup(p, "%u");
gmi->msg_size = UDP_HEADER_SIZE+8;
gmi->desc = apr_pstrdup(p, processDesc);
MMETRIC_INIT_METADATA(gmi,p);
MMETRIC_ADD_METADATA(gmi,MGROUP,"pcount");
processName = strtok(NULL," ");
}
/* Add a terminator to the array and replace the empty static metric
definition
array with the dynamic array that we just created
*/
gmi = apr_array_push(metric_info);
memset (gmi, 0, sizeof(*gmi));
cp_module.metrics_info = (Ganglia_25metric *)metric_info->elts;
return 0;
}
static void cp_metric_cleanup ( void )
{
}
static g_val_t cp_metric_handler ( int metric_index )
{
Ganglia_25metric *gmi = &(cp_module.metrics_info[metric_index]);
g_val_t val = count_procs(gmi->name);
return val;
}
mmodule cp_module =
{
STD_MMODULE_STUFF,
cp_metric_init,
cp_metric_cleanup,
NULL, /* Dynanically defined in cp_metric_init() */
cp_metric_handler,
};
#################### GDB Output ####################
d...@box:~/gmodules/ganglia-3.1.7/gmond/modules/cprocs# gdb /usr/sbin/gmond
GNU gdb (GDB) 7.1
<snip>
Reading symbols from /usr/sbin/gmond...(no debugging symbols found)...done.
(gdb) run -d1
Starting program: /usr/sbin/gmond -d1
Program received signal SIGSEGV, Segmentation fault.
0xb7f29ad6 in apr_array_push () from /usr/lib/libapr.so.0
################### GCC Syntax ##########################
from the ganglia-3.1.7/gmond/modules/mymodule directory:
cc mod_count_procs.c -shared -I/usr/include/proc -I/usr/include/apr/
-I../../../include/ -I../../../lib -lproc-3.2.7 -o modcprocs.so
------------------------------------------------------------------------------
Start uncovering the many advantages of virtual appliances
and start using them to simplify application deployment and
accelerate your shift to cloud computing.
http://p.sf.net/sfu/novell-sfdev2dev
_______________________________________________
Ganglia-general mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ganglia-general