afb-debug: add features for debugging
authorJosé Bollo <jose.bollo@iot.bzh>
Wed, 5 Jul 2017 11:39:27 +0000 (13:39 +0200)
committerJosé Bollo <jose.bollo@iot.bzh>
Wed, 5 Jul 2017 13:41:24 +0000 (15:41 +0200)
When compiled with -DAGL_DEVEL or -DAFB_INSERT_DEBUG_FEATURES
afb-daemon interprets the environment variables
AFB_DEBUG_BREAK and AFB_DEBUG_WAIT.

The environment variable AFB_DEBUG_BREAK make afb-daemon emit
a break (SIGINT) that should be treated by the debugger.

The environment variable AFB_DEBUG_WAIT make afb-daemon wait
for a break (SIGINT) to continue. This can be used to attach
a debugger.

The content of the variables AFB_DEBUG_BREAK and AFB_DEBUG_WAIT
is a list of key names of the point where the action should
occur. The list is separated by spaces or commas ','.

Example:

 AFB_DEBUG_WAIT=main-entry,start-load

The defined points are: main-entry, main-args, main-start,
start-entry, start-load, start-start, start-http, start-call,
start-exec.

Here some of their characteristic:
 - main-entry: at the beginning befaore any other instruction
 - main-args: after parsing arguments
 - main-start: after daemonisation before starting
 - start-entry: at start entry
 - start-load: before loading bindings after initialisation of afb-daemon
 - start-start: after loading bindings befaore starting it
 - start-call: after init before starting HTTP server
 - start-http: after http server, before calling startup calls
 - start-exec: before running the --exec command

Change-Id: Id405e749c590fb95f32e30a7d37c30b6412cf0a5
Signed-off-by: José Bollo <jose.bollo@iot.bzh>
src/CMakeLists.txt
src/afb-debug.c [new file with mode: 0644]
src/afb-debug.h [new file with mode: 0644]
src/main.c

index 9144194..31fcd51 100644 (file)
@@ -42,6 +42,7 @@ ADD_LIBRARY(afb-lib STATIC
        afb-config.c
        afb-context.c
        afb-cred.c
+       afb-debug.c
        afb-ditf.c
        afb-evt.c
        afb-hook.c
diff --git a/src/afb-debug.c b/src/afb-debug.c
new file mode 100644 (file)
index 0000000..5817f17
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ Copyright 2017 IoT.bzh
+
+ author: José Bollo <jose.bollo@iot.bzh>
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+#include "afb-debug.h"
+
+#if defined(AFB_INSERT_DEBUG_FEATURES)
+
+#define _GNU_SOURCE
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+
+#include "verbose.h"
+
+static char key_env_break[] = "AFB_DEBUG_BREAK";
+static char key_env_wait[] = "AFB_DEBUG_WAIT";
+static char separs[] = ", \t\n";
+
+static int has_key(const char *key, const char *list)
+{
+       if (list && key) {
+               list += strspn(list, separs);
+               while (*list) {
+                       size_t s = strcspn(list, separs);
+                       if (!strncasecmp(list, key, s) && !key[s])
+                               return 1;
+                       list += s;
+                       list += strspn(list, separs);
+               }
+       }
+       return 0;
+}
+
+static void handler(int signum)
+{
+}
+
+void afb_debug(const char *key)
+{
+       enum { None, Break, Wait } action;
+
+       if (has_key(key, secure_getenv(key_env_break)))
+               action = Break;
+       else if (has_key(key, secure_getenv(key_env_wait)))
+               action = Wait;
+       else
+               action = None;
+
+       if (action != None) {
+               const char *a = action == Break ? "BREAK" : "WAIT";
+               struct sigaction sa, psa;
+               sigset_t ss;
+
+               NOTICE("DEBUG %s before %s", a, key);
+               memset(&sa, 0, sizeof sa);
+               sa.sa_handler = handler;
+               sigaction(SIGINT, &sa, &psa);
+               if (action == Break) {
+                       raise(SIGINT);
+               } else {
+                       sigemptyset(&ss);
+                       sigaddset(&ss, SIGINT);
+                       sigwaitinfo(&ss, NULL);
+               }
+               sigaction(SIGINT, &psa, NULL);
+               NOTICE("DEBUG %s after %s", a, key);
+       }
+}
+
+#endif
+
diff --git a/src/afb-debug.h b/src/afb-debug.h
new file mode 100644 (file)
index 0000000..4723cd0
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ Copyright 2017 IoT.bzh
+
+ author: José Bollo <jose.bollo@iot.bzh>
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+#pragma once
+
+#if defined(AGL_DEVEL) && !defined(AFB_INSERT_DEBUG_FEATURES)
+# define AFB_INSERT_DEBUG_FEATURES
+#endif
+
+#if defined(AFB_INSERT_DEBUG_FEATURES)
+extern void afb_debug(const char *key);
+#else
+#define afb_debug(x)  ((void)0)
+#endif
index d099e1f..a989a70 100644 (file)
@@ -49,6 +49,7 @@
 #include "afb-monitor.h"
 #include "afb-hook.h"
 #include "sd-fds.h"
+#include "afb-debug.h"
 
 /*
    if SELF_PGROUP == 0 the launched command is the group leader
@@ -533,6 +534,8 @@ static void start(int signum)
 {
        struct afb_hsrv *hsrv;
 
+       afb_debug("start-entry");
+
        if (signum) {
                ERROR("start aborted: received signal %s", strsignal(signum));
                exit(1);
@@ -582,6 +585,7 @@ static void start(int signum)
                afb_hook_create_evt(NULL, config->traceevt, NULL, NULL);
 
        /* load bindings */
+       afb_debug("start-load");
        apiset_start_list(config->dbus_clients, afb_api_dbus_add_client, "the afb-dbus client");
        apiset_start_list(config->ws_clients, afb_api_ws_add_client, "the afb-websocket client");
        apiset_start_list(config->ldpaths, afb_api_so_add_pathset, "the binding path set");
@@ -593,10 +597,12 @@ static void start(int signum)
        DEBUG("Init config done");
 
        /* start the services */
+       afb_debug("start-start");
        if (afb_apiset_start_all_services(main_apiset, 1) < 0)
                goto error;
 
        /* start the HTTP server */
+       afb_debug("start-http");
        if (!config->noHttpd) {
                hsrv = start_http_server();
                if (hsrv == NULL)
@@ -604,9 +610,11 @@ static void start(int signum)
        }
 
        /* run the startup calls */
+       afb_debug("start-call");
        run_startup_calls();
 
        /* run the command */
+       afb_debug("start-exec");
        if (execute_command() < 0)
                goto error;
 
@@ -624,6 +632,8 @@ error:
 
 int main(int argc, char *argv[])
 {
+       afb_debug("main-entry");
+
        // let's run this program with a low priority
        nice(20);
 
@@ -632,6 +642,8 @@ int main(int argc, char *argv[])
        // ------------- Build session handler & init config -------
        config = afb_config_parse_arguments(argc, argv);
 
+       afb_debug("main-args");
+
        // --------- run -----------
        if (config->background) {
                // --------- in background mode -----------
@@ -646,6 +658,8 @@ int main(int argc, char *argv[])
        /* set the daemon environment */
        setup_daemon();
 
+       afb_debug("main-start");
+
        /* enter job processing */
        jobs_start(3, 0, 50, start);
        WARNING("hoops returned from jobs_enter! [report bug]");