Discussion:
[Libstoragemgmt-devel] [PATCH 2/4] C API: Enable valgrind tool with env variable V2
Tony Asleson
2014-03-31 19:00:33 UTC
Permalink
If you export LSM_VALGRIND the plug-in will invoke
the plug-in with valgrind so that we can debug memory
problems in compiled plug-ins. Output is written to
/tmp/leaking_<ppid>-<pid>.

V2: Make diskcheck work

Signed-off-by: Tony Asleson <***@redhat.com>
---
src/lsm_daemon.c | 39 ++++++++++++++++++++++++++++++++-------
test/runtests.sh | 43 +++++++++++++++++++++++++++++++++----------
test/tester.c | 10 ++++++++--
3 files changed, 73 insertions(+), 19 deletions(-)

diff --git a/src/lsm_daemon.c b/src/lsm_daemon.c
index 04eed85..81f838b 100644
--- a/src/lsm_daemon.c
+++ b/src/lsm_daemon.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011-2013 Red Hat, Inc.
+ * Copyright (C) 2011-2014 Red Hat, Inc.
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
@@ -70,6 +70,8 @@ char plugin_extension[] = "_lsmplugin";
typedef enum { RUNNING, RESTART, EXIT } serve_type;
serve_type serve_state = RUNNING;

+int plugin_mem_debug = 0;
+
/**
* Each item in plugin list contains this information
*/
@@ -502,8 +504,10 @@ void exec_plugin( char *plugin, int client_fd )

} else {
/* Child */
+ int exec_rc = 0;
char fd_str[12];
- char *plugin_argv[3];
+ char *plugin_argv[7];
+ extern char **environ;

/* Make copy of plug-in string as once we call empty_plugin_list it
* will be deleted :-) */
@@ -512,12 +516,28 @@ void exec_plugin( char *plugin, int client_fd )
empty_plugin_list(&head);
sprintf(fd_str, "%d", client_fd);

- plugin_argv[0] = basename(p_copy);
- plugin_argv[1] = fd_str;
- plugin_argv[2] = NULL;
- extern char **environ;
+ if( plugin_mem_debug ) {
+ char debug_out[64];
+ snprintf(debug_out, (sizeof(debug_out) - 1),
+ "--log-file=/tmp/leaking_%d-%d", getppid(), getpid());

- if( -1 == execve(p_copy, plugin_argv, environ)) {
+ plugin_argv[0] = "valgrind";
+ plugin_argv[1] = "--leak-check=full";
+ plugin_argv[2] = "--show-reachable=yes";
+ plugin_argv[3] = debug_out;
+ plugin_argv[4] = p_copy;
+ plugin_argv[5] = fd_str;
+ plugin_argv[6] = NULL;
+
+ exec_rc = execve("/usr/bin/valgrind", plugin_argv, environ);
+ } else {
+ plugin_argv[0] = basename(p_copy);
+ plugin_argv[1] = fd_str;
+ plugin_argv[2] = NULL;
+ exec_rc = execve(p_copy, plugin_argv, environ);
+ }
+
+ if( -1 == exec_rc ) {
int err = errno;
loud("Error on exec'ing Plugin %s: %s\n",
p_copy, strerror(err));
@@ -669,6 +689,11 @@ int main(int argc, char *argv[])
openlog("lsmd", LOG_ODELAY, LOG_USER);
}

+ /* Check to see if we want to check plugin for memory errors */
+ if( getenv("LSM_VALGRIND") ) {
+ plugin_mem_debug = 1;
+ }
+
install_sh();
drop_privileges();
flight_check();
diff --git a/test/runtests.sh b/test/runtests.sh
index 60c245c..b94565a 100755
--- a/test/runtests.sh
+++ b/test/runtests.sh
@@ -1,6 +1,6 @@
#!/bin/bash

-# Copyright (C) 2011-2013 Red Hat, Inc.
+# Copyright (C) 2011-2014 Red Hat, Inc.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
@@ -49,7 +49,7 @@ good() {
fi
}

-#Put us in a consistant spot
+#Put us in a consistent spot
cd "$(dirname "$0")"

#Get base root directory
@@ -59,16 +59,27 @@ rootdir=${testdir%/*}
#Are we running within distcheck?
c_unit=$rootdir/test/tester
LSMD_DAEMON=$rootdir/src/lsmd
+shared_libs=$rootdir/src/.libs/
+bin_plugin=$rootdir/plugin/.libs/
+
+
if [ -e $rootdir/_build ]
then
c_unit=$rootdir/_build/test/tester
LSMD_DAEMON=$rootdir/_build/src/lsmd
+ shared_libs=$rootdir/_build/src/.libs/
+ bin_plugin=$rootdir/_build/plugin/.libs/
fi

-#With a distcheck you cannot much with the source file system, so we will copy
+#With a distcheck you cannot muck with the source file system, so we will copy
#plugins somewhere else.
plugins=$base/plugins

+#Export needed vars
+export PYTHONPATH=$rootdir/lsm
+export LD_LIBRARY_PATH=$base/lib
+export LSM_SIM_DATA="$base/lsm_sim_data"
+
echo "testdir= $testdir"
echo "rootdir= $rootdir"
echo "c_unit= $c_unit"
@@ -76,27 +87,39 @@ echo "c_unit= $c_unit"
#Create the directory for the unix domain sockets
good "mkdir -p $LSM_UDS_PATH"
good "mkdir -p $plugins"
+good "mkdir -p $LD_LIBRARY_PATH"
+
+#Copy shared libraries
+good "cp $shared_libs/*.so.* $LD_LIBRARY_PATH"

#Copy plugins to one directory.
good "find $rootdir/ \( ! -regex '.*/\..*' \) -type f -name \*_lsmplugin -exec cp {} $plugins \;"

-#Export needed vars
-export PYTHONPATH=$rootdir/lsm
-export LD_LIBRARY_PATH=$rootdir/src
-export LSM_SIM_DATA="$base/lsm_sim_data"
+#Copy the actual binary, not the shell script pointing to binary otherwise
+#valgrind does not work.
+good "cp $bin_plugin/*_lsmplugin $plugins"
+good "ls -lh $plugins"
+
+

#Start daemon
good "$LSMD_DAEMON --plugindir $plugins --socketdir $LSM_UDS_PATH" -v

LSMD_PID=$(ps aux | grep $LSM_UDS_PATH | grep -v grep | awk '{print $2}')

+export G_SLICE=always-malloc
+export G_DEBUG=gc-friendly
+
#Run C unit test
export CK_DEFAULT_TIMEOUT=600
+export CK_export CK_FORK=no
good "$c_unit"

-#Run cmdline against the simulator
-export LSMCLI_URI='sim://'
-good "$rootdir/test/cmdtest.py -c $rootdir/tools/lsmclipy/lsmcli"
+#Run cmdline against the simulator if we are not checking for leaks
+if [ -z "$LSM_VALGRIND" ]; then
+ export LSMCLI_URI='sim://'
+ good "$rootdir/test/cmdtest.py -c $rootdir/tools/lsmclipy/lsmcli"
+fi

#Pretend we were never here
cleanup
diff --git a/test/tester.c b/test/tester.c
index d9f72a3..f964c9f 100644
--- a/test/tester.c
+++ b/test/tester.c
@@ -2650,9 +2650,15 @@ int main(int argc, char** argv)
Suite *s = lsm_suite();
SRunner *sr = srunner_create(s);

- srunner_run_all(sr, CK_NORMAL);
+ /*
+ * Don't run python plug-in tests if we are looking for
+ * memory leaks.
+ */
+ if( !getenv("LSM_VALGRIND") ) {
+ srunner_run_all(sr, CK_NORMAL);
+ }

- /* Switch plugin backend to test cross language compat. */
+ /* Switch plug-in backend to test C language compat. */
which_plugin = 1;

srunner_run_all(sr, CK_NORMAL);
--
1.8.2.1
Loading...