Hi Anders,

thanks I'll update, regarding the -lgcov it should not be included, just the --coverage should be necessary, it is according to gcc

documentation a synonym for -fprofile-arcs, -ftest-coverage when compiling and -lgcov when linking.

/Regards HansN


On 09/27/2017 12:03 PM, Anders Widell wrote:
Ack with comments, marked AndersW> in the code below.

A general comment is that this solution only works with IPv4, not with IPv6 or TIPC. It might also have problems with IPv4 if the nodes have multiple network interfaces, since you let the kernel select which interface to use. However since this is just a debug tool it doesn't really matter much that the solution isn't generic for any choice of communication mechanism.

regards,

Anders Widell


On 09/21/2017 04:25 PM, Hans Nordeback wrote:
---
  00-README.conf                            | 13 ++++-
  Makefile.am                               |  8 ++-
  README                                    |  1 +
  configure.ac                              | 18 ++++++
  src/base/daemon.c                         | 96 +++++++++++++++++++++++++++++--
  src/nid/opensafd.in                       |  7 +++
  tools/devel/gcov_collect/osaf_gcov_dump.c | 40 +++++++++++++
  7 files changed, 176 insertions(+), 7 deletions(-)
  create mode 100644 tools/devel/gcov_collect/osaf_gcov_dump.c

diff --git a/00-README.conf b/00-README.conf
index f64aa031c..c42a37563 100644
--- a/00-README.conf
+++ b/00-README.conf
@@ -610,4 +610,15 @@ A message will be written if the latency is > 0.1 second, example below shows a     messages.1:Sep 12 13:09:26 SC-1 osafimmd[26732]: NO MDS timerfd expired 10 times   -If the latency exceeds 4 seconds a sigalrm will be sent and the process will be aborted.
\ No newline at end of file
+If the latency exceeds 4 seconds a sigalrm will be sent and the process will be aborted.
+
+# To enable gcov run ./configure --enable-gcov
+# In each daemon a thread will be created that listens to a default multicast group 239.0.0.1 port 4712. +# To change default, update /etc/init.d/opensafd setup_env function, example:
+# export OPENSAF_GCOV_MULTICAST_GROUP="224.0.0.1"
+# export OPENSAF_GCOV_MULTICAST_PORT="4711"
+# and if running in UML uncomment the line:
+# echo 100 >  /proc/sys/net/ipv4/igmp_max_memberships
+# To collect gcov data use program tools/develop/gcov_collect/osaf_gcov_dump. +# Check the MULTICAST_PORT and MULTICAST_GROUP settings are the same as multicast group and port
+# above.
\ No newline at end of file
diff --git a/Makefile.am b/Makefile.am
index 7763f313c..0a69f752d 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -56,7 +56,13 @@ AM_CPPFLAGS = \
    AM_CFLAGS = -pipe -std=gnu11 @OSAF_HARDEN_FLAGS@ -Wall -Wformat=2 -Werror   AM_CXXFLAGS = -pipe -std=gnu++11 @OSAF_HARDEN_FLAGS@ -Wall -Wformat=2 -Werror -AM_LDFLAGS = @OSAF_HARDEN_FLAGS@ -Wl,--as-needed -ldl -lrt -pthread -rdynamic
+
+if ENABLE_GCOV
+AM_CFLAGS += --coverage
+AM_CXXFLAGS += --coverage
+endif
+
+AM_LDFLAGS = @OSAF_HARDEN_FLAGS@ -Wl,--as-needed -ldl -lrt -pthread -rdynamic -lgcov

AndersW> Why isn't the addition of -lgcov guarded by the "if ENABLE_GCOV" clause above? I think it ought to be.

  ACLOCAL_AMFLAGS = -I m4
  OSAF_LIB_FLAGS =
  diff --git a/README b/README
index 13c0eb352..d51314a4b 100644
--- a/README
+++ b/README
@@ -534,6 +534,7 @@ available w.r.t enabling/disabling the build for a particular OpenSAF service:
                            produced.
    --disable-rpm-target    disable support for the "make rpm" target
                            [default=no]
+  --enable-gcov           enable code coverage [default=no]
    --enable-experimental   enable experimental code [default=no]
    --enable-python         enable the Python AIS bindings [default=yes]
    --enable-java           enable the Java AIS interface mapping [default=no]
diff --git a/configure.ac b/configure.ac
index 74655ddce..56b17ab36 100644
--- a/configure.ac
+++ b/configure.ac
@@ -188,6 +188,24 @@ fi
  AM_CONDITIONAL([ENABLE_EXPERIMENTAL], [test "$enable_experimental" = yes])
  AC_SUBST([EXPERIMENTAL_ENABLED], ["$enable_experimental"])
  +#
+# Enable/disable gcov
+#
+AC_MSG_CHECKING([whether to build with gcov])
+AC_ARG_ENABLE([gcov],
+        [AS_HELP_STRING([--enable-gcov],
+                [enable building with gcov [default=no]])],
+        [],
+        [enable_gcov=no])
+AC_MSG_RESULT([$enable_gcov])
+
+if test "$enable_gcov" = yes; then
+        AC_DEFINE([ENABLE_GCOV], 1, [Define if gcov is enabled])
+fi
+
+AM_CONDITIONAL([ENABLE_GCOV], [test "$enable_gcov" = yes])
+AC_SUBST([GCOV_ENABLED], ["$enable_gcov"])
+
  #
  # Enable/disable the Python AIS bindings
  #
diff --git a/src/base/daemon.c b/src/base/daemon.c
index 575588575..3e6ca7357 100644
--- a/src/base/daemon.c
+++ b/src/base/daemon.c
@@ -15,7 +15,13 @@
   * Author(s): Wind River Systems
   *
   */
+#ifdef HAVE_CONFIG_H
+#include "osaf/config.h"
+#endif
  +#include <pthread.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
  #include <ctype.h>
  #include <sched.h>
  #include <stdio.h>
@@ -56,8 +62,6 @@
    static const char *internal_version_id_;
  -extern void __gcov_flush(void) __attribute__((weak));
-
  static char fifo_file[NAME_MAX];
  static char __pidfile[NAME_MAX];
  static char __tracefile[NAME_MAX];
@@ -69,6 +73,87 @@ static int fifo_fd = -1;
    static void install_fatal_signal_handlers(void);
  +#ifdef ENABLE_GCOV
+
+// default multicast group for gcov collection
+#define DFLT_MULTICAST_GROUP "239.0.0.1"
+
+extern void __gcov_dump();
+extern void __gcov_reset();
+
+static void* gcov_flush_thread(void* arg) {
+    int listenfd;
+    const int on = 1;
+    struct sockaddr_in servaddr;
+    struct ip_mreq mreq;
+    char buf[40];
+    struct sockaddr_in addr;
+    socklen_t addr_len;
+    int multicast_port = 4712; // default multicast group for gcov collection
+    const char *multicast_port_str;
+    const char *multicast_group;
+
+    if ((multicast_group = getenv("OPENSAF_GCOV_MULTICAST_GROUP")) == NULL) {
+        multicast_group = DFLT_MULTICAST_GROUP;
+    }
+
+    if ((multicast_port_str = getenv("OPENSAF_GCOV_MULTICAST_PORT")) != NULL) {
+        multicast_port = strtol(multicast_port_str, NULL, 0);
+    }
+
+    listenfd = socket(AF_INET, SOCK_DGRAM, 0);
+
+    if ((setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1)) { +        syslog(LOG_ERR, "%s: setsockpot failed: %s", __FUNCTION__, strerror(errno));
+        return 0;
+    }
+
+    memset(&servaddr, 0, sizeof(servaddr));
+    servaddr.sin_family = AF_INET;
+    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
+    servaddr.sin_port = htons(multicast_port);
+
+    if (bind(listenfd, (struct sockaddr*) &servaddr, sizeof(servaddr)) < 0) { +        syslog(LOG_ERR, "%s: bind failed: %s", __FUNCTION__, strerror(errno));
+        return 0;
+    }
+
+    //

AndersW> The line above contains an empty comment? Remove it, or add some text.

+ mreq.imr_multiaddr.s_addr=inet_addr(multicast_group);
+    mreq.imr_interface.s_addr=htonl(INADDR_ANY);
+    if (setsockopt(listenfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) { +        syslog(LOG_ERR, "%s: setsockopt failed: %s", __FUNCTION__, strerror(errno));
+        return 0;
+    } else {
+        syslog(LOG_NOTICE, "%s: joined multicast group %s port %d\n",
+            __FUNCTION__, multicast_group, multicast_port);
+    }
+
+    for(;;) {
+        addr_len = sizeof(addr);
+        recvfrom(listenfd, &buf, sizeof(buf), 0, (struct sockaddr *) &addr, &addr_len);
+        __gcov_dump();
+        __gcov_reset();
+        syslog(LOG_NOTICE, "__gov_dump() and __gcov_reset() called");
+    }
+    return 0;
+};

AndersW> Unnecessary semicolon on the line above.

+
+static void create_gcov_flush_thread(void) {
+    pthread_t thread;
+    pthread_attr_t attr;
+    pthread_attr_init(&attr);
+    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+
+    if (pthread_create(&thread, &attr, gcov_flush_thread, 0) != 0) {
+        syslog(LOG_ERR, "pthread_create FAILED: %s", strerror(errno));
+    }

AndersW> I think it would be useful if we can disable the thread at runtime. Maybe you can read the environment variable here and check e.g. if OPENSAF_GCOV_MULTICAST_PORT is "0" or the empty string, and in that case skip creating the thread.
+
+    pthread_attr_destroy(&attr);
+}
+
+#endif
+
  static void __print_usage(const char *progname, FILE *stream, int exit_code)
  {
      fprintf(stream, "Usage:  %s [OPTIONS]...\n", progname);
@@ -398,6 +483,10 @@ void daemonize(int argc, char *argv[])
        create_fifofile(fifo_file);
  +#ifdef ENABLE_GCOV
+    create_gcov_flush_thread();
+#endif
+
      /* Create the process PID file */
      if (__create_pidfile(__pidfile) != 0)
          exit(EXIT_FAILURE);
@@ -537,9 +626,6 @@ void daemon_exit(void)
      unlink(fifo_file);
      unlink(__pidfile);
  -    if (__gcov_flush) {
-        __gcov_flush();
-    }
      _Exit(0);
  }
  diff --git a/src/nid/opensafd.in b/src/nid/opensafd.in
index 428b222c2..effe87d41 100644
--- a/src/nid/opensafd.in
+++ b/src/nid/opensafd.in
@@ -72,6 +72,13 @@ check_tipc() {
  }
    setup_env() {
+    # The following lines if --enable-gcov is configured
+    # If running in UML uncomment the next line
+    # echo 100 >  /proc/sys/net/ipv4/igmp_max_memberships
+    # gcov collecton is using multicast, to change default multicast group and multicast group:
+    # export OPENSAF_GCOV_MULTICAST_GROUP="224.0.0.1"
+    # export OPENSAF_GCOV_MULTICAST_PORT="4711"
+
      # Make sure this kernel has POSIX shared memory configured
      if [ ! -d /dev/shm ]; then
          logger -s -t $osafprog "POSIX shared memory (/dev/shm) not enabled, exiting." diff --git a/tools/devel/gcov_collect/osaf_gcov_dump.c b/tools/devel/gcov_collect/osaf_gcov_dump.c
new file mode 100644
index 000000000..9999d2b51
--- /dev/null
+++ b/tools/devel/gcov_collect/osaf_gcov_dump.c
@@ -0,0 +1,40 @@
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+// gcc -g -o osaf_gcov_dump osaf_gcov_dump.c
+#define MULTICAST_PORT 4712
+#define MULTICAST_GROUP "239.0.0.1"
+
+int main()
+{
+    struct sockaddr_in addr;
+    int fd, cnt;
+    struct ip_mreq mreq;
+    const char message[] = "Not used";
+
+    if ((fd = socket(AF_INET, SOCK_DGRAM,0)) < 0) {
+        perror("socket");
+        exit(1);
+    }
+
+    memset(&addr,0,sizeof(addr));
+    addr.sin_family=AF_INET;
+    addr.sin_addr.s_addr=inet_addr(MULTICAST_GROUP);
+    addr.sin_port=htons(MULTICAST_PORT);
+
+    if (sendto(fd, message, sizeof(message), 0, (struct sockaddr *) &addr,
+           sizeof(addr)) < 0) {
+        perror("sendto");
+    } else {
+        printf("sendto %s %d ok!\n", MULTICAST_GROUP, MULTICAST_PORT);
+    }
+    return 0;
+}



------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Opensaf-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/opensaf-devel

Reply via email to