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

Reply via email to