LCOV - code coverage report
Current view: top level - console/logstorage - dlt-logstorage-ctrl.c (source / functions) Coverage Total Hit
Test: dlt_final_coverage.info Lines: 21.5 % 191 41
Test Date: 2026-08-27 10:11:10 Functions: 30.8 % 13 4

            Line data    Source code
       1              : /**
       2              :  * Copyright (C) 2013 - 2015  Advanced Driver Information Technology.
       3              :  * This code is developed by Advanced Driver Information Technology.
       4              :  * Copyright of Advanced Driver Information Technology, Bosch and DENSO. *
       5              :  * This file is part of COVESA Project Dlt - Diagnostic Log and Trace console apps.
       6              :  *
       7              :  *
       8              :  * \copyright
       9              :  * This Source Code Form is subject to the terms of the
      10              :  * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with
      11              :  * this file, You can obtain one at http://mozilla.org/MPL/2.0/.
      12              :  *
      13              :  *
      14              :  * \author Syed Hameed <shameed@jp.adit-jv.com> ADIT 2013 - 2015
      15              :  * \author Christoph Lipka <clipka@jp.adit-jv.com> ADIT 2015
      16              :  * \author Frederic Berat <fberat@de.adit-jv.com> ADIT 2015
      17              :  *
      18              :  * \file dlt-logstorage-ctrl.c
      19              :  * For further information see http://www.covesa.org/.
      20              :  */
      21              : /*******************************************************************************
      22              : **                                                                            **
      23              : **  SRC-MODULE: dlt-logstorage-ctrl.c                                         **
      24              : **                                                                            **
      25              : **  TARGET    : linux                                                         **
      26              : **                                                                            **
      27              : **  PROJECT   : DLT                                                           **
      28              : **                                                                            **
      29              : **  AUTHOR    : Syed Hameed shameed@jp.adit-jv.com                            **
      30              : **              Christoph Lipka clipka@jp.adit-jv.com                         **
      31              : **              AnithaAmmaji.baggam@in.bosch.com                              **
      32              : **              Frederic Berat fberat@de.adit-jv.com                          **
      33              : **  PURPOSE   :                                                               **
      34              : **                                                                            **
      35              : **  REMARKS   :                                                               **
      36              : **                                                                            **
      37              : **  PLATFORM DEPENDANT [yes/no]: yes                                          **
      38              : **                                                                            **
      39              : **  TO BE CHANGED BY USER [yes/no]: no                                        **
      40              : **                                                                            **
      41              : *******************************************************************************/
      42              : 
      43              : /*******************************************************************************
      44              : **                      Author Identity                                       **
      45              : ********************************************************************************
      46              : ** Initials     Name                       Company                            **
      47              : ** --------     -------------------------  ---------------------------------- **
      48              : **  sh          Syed Hameed                ADIT                               **
      49              : **  cl          Christoph Lipka            ADIT                               **
      50              : **  BA          Anitha BA                  ADIT                               **
      51              : **  fb          Frederic Berat             ADIT                               **
      52              : *******************************************************************************/
      53              : 
      54              : #define pr_fmt(fmt) "Logstorage control: " fmt
      55              : 
      56              : #include <ctype.h>
      57              : #include <errno.h>
      58              : #include <stdio.h>
      59              : #include <stdlib.h>
      60              : #include <signal.h>
      61              : #include <string.h>
      62              : #include <getopt.h>
      63              : 
      64              : #include <poll.h>
      65              : 
      66              : #if defined(__linux__)
      67              : #include "sd-daemon.h"
      68              : #endif
      69              : 
      70              : #include "dlt_protocol.h"
      71              : #include "dlt_client.h"
      72              : #include "dlt-control-common.h"
      73              : #include "dlt-logstorage-common.h"
      74              : #include "dlt-logstorage-ctrl.h"
      75              : 
      76              : #define POLL_TIME_OUT 500
      77              : #define EV_MASK_REJECTED (POLLERR | POLLHUP | POLLNVAL)
      78              : 
      79              : #define DLT_LOGSTORAGE_CTRL_EXIT 1
      80              : static int must_exit;
      81              : struct dlt_event {
      82              :     struct pollfd pfd;
      83              :     void* func;
      84              : };
      85              : 
      86              : /** @brief Triggers the application exit
      87              :  *
      88              :  * The application will exit on next poll timeout.
      89              :  */
      90            0 : void dlt_logstorage_exit(void)
      91              : {
      92            0 :     must_exit = DLT_LOGSTORAGE_CTRL_EXIT;
      93            0 : }
      94              : 
      95              : /** @brief Check if the application must exit
      96              :  *
      97              :  * The application will exit on next poll timeout.
      98              :  */
      99            0 : int dlt_logstorage_must_exit(void)
     100              : {
     101            0 :     return must_exit;
     102              : }
     103              : 
     104              : /** @brief Signal handler.
     105              :  *
     106              :  * Triggers the exit of the application in case of specific signals
     107              :  *
     108              :  * @param signo The value of the signal received.
     109              :  */
     110            0 : static void catch_signal(int signo)
     111              : {
     112            0 :     if (signo) {
     113            0 :         pr_error("Signal %d received, exiting.", signo);
     114              :         dlt_logstorage_exit();
     115              :     }
     116            0 : }
     117              : 
     118              : /** @brief Install a handler for some signals
     119              :  *
     120              :  * Handler are installed on exit related signals. That allows one to exit from
     121              :  * the main loop gracefully.
     122              :  */
     123            0 : static void install_signal_handler(void)
     124              : {
     125            0 :     int signals[] = {SIGINT, SIGQUIT, SIGTERM, 0};
     126              :     unsigned int i;
     127              :     struct sigaction sa;
     128              : 
     129            0 :     pr_verbose("Installing signal handler.\n");
     130              : 
     131              :     /* install a signal handler for the above listed signals */
     132            0 :     for (i = 0; signals[i]; i++) {
     133              :         memset(&sa, 0, sizeof(sa));
     134            0 :         sa.sa_handler = catch_signal;
     135              : 
     136            0 :         if (sigaction(signals[i], &sa, NULL) < 0)
     137            0 :             pr_error("Failed to install signal %u handler. Error: %s\n", signals[i], strerror(errno));
     138              :     }
     139            0 : }
     140              : 
     141              : #define MAX_RESPONSE_LENGTH 32
     142              : /** @brief Analyze the daemon answer to a request
     143              :  *
     144              :  * This function checks whether if the daemon answered positively to
     145              :  * the request or not.
     146              :  *
     147              :  * @param data    The textual answer
     148              :  * @param payload The answer payload
     149              :  * @param len     The answer payload length
     150              :  * @return 0 on success, -1 otherwise.
     151              :  */
     152            1 : static int analyze_response(char* data, void* payload, int len)
     153              : {
     154              :     int ret = -1;
     155            1 :     char resp_ok[MAX_RESPONSE_LENGTH] = {0};
     156            1 :     char resp_warning[MAX_RESPONSE_LENGTH] = {0};
     157            1 :     char resp_perm_denied[MAX_RESPONSE_LENGTH] = {0};
     158              : 
     159            1 :     if ((data == NULL) || (payload == NULL))
     160              :         return -1;
     161              : 
     162              :     /* satisfy compiler */
     163              :     (void)payload;
     164              :     (void)len;
     165              : 
     166              :     snprintf(resp_ok, MAX_RESPONSE_LENGTH, "service(%d), ok", DLT_SERVICE_ID_OFFLINE_LOGSTORAGE);
     167              : 
     168              :     snprintf(resp_warning, MAX_RESPONSE_LENGTH, "service(%d), warning", DLT_SERVICE_ID_OFFLINE_LOGSTORAGE);
     169              : 
     170              :     snprintf(resp_perm_denied, MAX_RESPONSE_LENGTH, "service(%d), perm_denied", DLT_SERVICE_ID_OFFLINE_LOGSTORAGE);
     171              : 
     172            1 :     if (strncmp(data, resp_ok, strlen(resp_ok)) == 0)
     173              :         ret = 0;
     174              : 
     175            1 :     if (strncmp(data, resp_warning, strlen(resp_warning)) == 0) {
     176            0 :         pr_error("Warning:Some filter configurations are ignored due to configuration issues \n");
     177              :         ret = 0;
     178              :     }
     179              : 
     180            1 :     if (strncmp(data, resp_perm_denied, strlen(resp_perm_denied)) == 0) {
     181            0 :         pr_error("Warning: Permission denied.\n");
     182              :         ret = 0;
     183              :     }
     184              : 
     185            1 :     pr_verbose("Response received: '%s'\n", data);
     186            1 :     pr_verbose("Response expected: '%s'\n", resp_ok);
     187              : 
     188              :     return ret;
     189              : }
     190              : 
     191              : /** @brief Add a new event to watch
     192              :  *
     193              :  * This function could be exported to be used by udev/prop so that they can
     194              :  * register several events.
     195              :  *
     196              :  * @param ev_hdl The structure containing the file descriptors
     197              :  * @param fd The file descriptor to watch
     198              :  * @param cb The callback to be called on event.
     199              :  *
     200              :  * @return 0 on success, -1 if the parameters are invalid.
     201              :  */
     202            0 : static int dlt_logstorage_ctrl_add_event(struct dlt_event* ev_hdl, int fd, void* cb)
     203              : {
     204            0 :     if ((fd < 0) || !cb || !ev_hdl) {
     205            0 :         pr_error("Wrong parameter to add event (%d %p)\n", fd, cb);
     206            0 :         return -1;
     207              :     }
     208              : 
     209            0 :     pr_verbose("Setting up the event handler with (%d, %p).\n", fd, cb);
     210              : 
     211            0 :     ev_hdl->func = cb;
     212            0 :     ev_hdl->pfd.fd = fd;
     213              : 
     214            0 :     return 0;
     215              : }
     216              : 
     217              : /** @brief Main execution loop
     218              :  *
     219              :  * Waits on events, and executes the callbacks retrieved
     220              :  * back from the event structure.
     221              :  *
     222              :  * @return 0 on success, -1 otherwise.
     223              :  */
     224            0 : static int dlt_logstorage_ctrl_execute_event_loop(struct dlt_event* ev)
     225              : {
     226              :     int ret = 0;
     227              :     union {
     228              :         void* ptr;
     229              :         int (*callback)(void);
     230              :     } callback_converter;
     231              :     int (*callback)(void);
     232              : 
     233            0 :     callback_converter.ptr = ev->func;
     234            0 :     callback = callback_converter.callback;
     235              : 
     236            0 :     ret = poll(&ev->pfd, 1, POLL_TIME_OUT);
     237              : 
     238            0 :     if (ret <= 0) {
     239            0 :         if (errno == EINTR)
     240              :             ret = 0;
     241              : 
     242            0 :         if (ret < 0)
     243            0 :             pr_error("poll error: %s\n", strerror(errno));
     244              : 
     245            0 :         return ret;
     246              :     }
     247              : 
     248            0 :     if (ev->pfd.revents == 0)
     249              :         return 0;
     250              : 
     251            0 :     if (ev->pfd.events & EV_MASK_REJECTED) {
     252            0 :         pr_error("Error while polling. Event received: 0x%x\n", ev->pfd.events);
     253              :         /* We only support one event producer.
     254              :          * Error means that this producer died.
     255              :          */
     256            0 :         pr_error("Now closing fd and exiting.\n");
     257            0 :         close(ev->pfd.fd);
     258            0 :         ev->pfd.fd = -1;
     259              :         dlt_logstorage_exit();
     260            0 :         return -1;
     261              :     }
     262              : 
     263            0 :     if (!callback) {
     264            0 :         pr_error("Callback not found, exiting.\n");
     265              :         dlt_logstorage_exit();
     266            0 :         return -1;
     267              :     }
     268              : 
     269              :     callback_converter.callback = callback;
     270            0 :     pr_verbose("Got new event, calling %p.\n", callback_converter.ptr);
     271              : 
     272            0 :     if (callback() < 0) {
     273            0 :         pr_error("Error while calling the callback, exiting.\n");
     274              :         dlt_logstorage_exit();
     275            0 :         return -1;
     276              :     }
     277              : 
     278              :     return 0;
     279              : }
     280              : 
     281              : /** @brief Start event loop and receive messages from DLT.
     282              :  *
     283              :  * The function will first install the signal handler,
     284              :  * then create the poll instance, initialize the communication controller,
     285              :  * initialize the event handler and finally start the polling.
     286              :  *
     287              :  * @return 0 on success, -1 on error
     288              :  */
     289            0 : static int dlt_logstorage_ctrl_setup_event_loop(void)
     290              : {
     291              :     int ret = 0;
     292            0 :     struct dlt_event ev_hdl = {.pfd = {.fd = -1, .events = POLLIN}};
     293              : 
     294            0 :     install_signal_handler();
     295              : 
     296            0 :     pr_verbose("Creating poll instance.\n");
     297              : 
     298              :     /* Initializing the communication with the daemon */
     299            0 :     while (dlt_control_init(analyze_response, get_ecuid(), get_verbosity()) && !dlt_logstorage_must_exit()) {
     300            0 :         pr_error("Failed to initialize connection with the daemon.\n");
     301            0 :         pr_error("Retrying to connect in %ds.\n", get_timeout());
     302            0 :         sleep((unsigned int)get_timeout());
     303              :     }
     304              : 
     305            0 :     if (dlt_logstorage_must_exit()) {
     306            0 :         pr_verbose("Exiting.\n");
     307            0 :         return 0;
     308              :     }
     309              : 
     310            0 :     pr_verbose("Initializing event generator.\n");
     311              : 
     312            0 :     if (dlt_logstorage_init_handler() < 0) {
     313            0 :         pr_error("Failed to initialize handler.\n");
     314            0 :         dlt_control_deinit();
     315            0 :         return -1;
     316              :     }
     317              : 
     318            0 :     if (dlt_logstorage_ctrl_add_event(&ev_hdl, dlt_logstorage_get_handler_fd(), dlt_logstorage_get_handler_cb()) < 0) {
     319            0 :         pr_error("add_event error: %s\n", strerror(errno));
     320              :         dlt_logstorage_exit();
     321              :     }
     322              : 
     323            0 :     while (!dlt_logstorage_must_exit() && (ret == 0))
     324            0 :         ret = dlt_logstorage_ctrl_execute_event_loop(&ev_hdl);
     325              : 
     326              :     /* Clean up */
     327            0 :     dlt_logstorage_deinit_handler();
     328            0 :     dlt_control_deinit();
     329              : 
     330            0 :     return ret;
     331              : }
     332              : 
     333              : /** @brief Send a single command to DLT daemon and wait for response
     334              :  *
     335              :  * @return 0 on success, -1 otherwise.
     336              :  */
     337            1 : static int dlt_logstorage_ctrl_single_request()
     338              : {
     339              :     int ret = 0;
     340              : 
     341              :     /* in case sync all caches, an empty path is given */
     342            1 :     if (get_default_event_type() != EVENT_SYNC_CACHE) {
     343              :         /* Check if a 'CONF_NAME' file is present at the given path */
     344            0 :         if (!dlt_logstorage_check_config_file(get_default_path())) {
     345            0 :             pr_error("No '%s' file available at: %s\n", CONF_NAME, get_default_path());
     346            0 :             return -1;
     347              :         }
     348              : 
     349            0 :         if (!dlt_logstorage_check_directory_permission(get_default_path())) {
     350            0 :             pr_error("'%s' is not writable\n", get_default_path());
     351            0 :             return -1;
     352              :         }
     353              :     }
     354              : 
     355              :     /* Initializing the communication with the daemon */
     356            1 :     while (dlt_control_init(analyze_response, get_ecuid(), get_verbosity()) && !dlt_logstorage_must_exit()) {
     357            0 :         pr_error("Failed to initialize connection with the daemon.\n");
     358            0 :         pr_error("Retrying to connect in %ds.\n", get_timeout());
     359            0 :         sleep((unsigned int)get_timeout());
     360              :     }
     361              : 
     362            1 :     pr_verbose("event type is [%d]\t device path is [%s]\n", get_default_event_type(), get_default_path());
     363              : 
     364            1 :     ret = dlt_logstorage_send_event(get_default_event_type(), get_default_path());
     365              : 
     366            1 :     dlt_control_deinit();
     367              : 
     368            1 :     return ret;
     369              : }
     370              : 
     371              : /** @brief Print out the application help
     372              :  */
     373            0 : static void usage(void)
     374              : {
     375              :     printf("Usage: dlt-logstorage-ctrl [options]\n");
     376              :     printf(
     377              :         "Send a trigger to DLT daemon to connect/disconnect"
     378              :         "a certain logstorage device\n");
     379              :     printf("\n");
     380              :     printf("Options:\n");
     381              :     printf("  -c --command               Connection type: connect = 1, disconnect = 0\n");
     382              :     printf("  -d[prop] --daemonize=prop  Run as daemon: prop = use proprietary handler\n");
     383              :     printf("                             'prop' may be replaced by any meaningful word\n");
     384              :     printf("                             If prop is not specified, udev will be used\n");
     385              :     printf("  -e --ecuid                 Set ECU ID (Default: %s)\n", DLT_CTRL_DEFAULT_ECUID);
     386              :     printf("  -h --help                  Usage\n");
     387              :     printf("  -p --path                  Mount point path\n");
     388              :     printf("  -s[path] --snapshot=path   Sync Logstorage cache\n");
     389              :     printf("                             Don't use -s together with -d and -c\n");
     390              :     printf("  -t                         Specify connection timeout (Default: %ds)\n", DLT_CTRL_TIMEOUT);
     391              :     printf("  -S --send-header           Send message with serial header (Default: Without serial header)\n");
     392              :     printf("  -R --resync-header         Enable resync serial header\n");
     393            0 :     printf("  -v --verbose               Set verbose flag (Default:%d)\n", get_verbosity());
     394              :     printf("  -C filename                DLT daemon configuration file (Default: " CONFIGURATION_FILES_DIR
     395              :            "/dlt.conf)\n");
     396            0 : }
     397              : 
     398              : static struct option long_options[] = {
     399              :     {"command", required_argument, 0, 'c'},
     400              :     {"daemonize", optional_argument, 0, 'd'},
     401              :     {"ecuid", required_argument, 0, 'e'},
     402              :     {"help", no_argument, 0, 'h'},
     403              :     {"path", required_argument, 0, 'p'},
     404              :     {"snapshot", optional_argument, 0, 's'},
     405              :     {"timeout", required_argument, 0, 't'},
     406              :     {"send-header", no_argument, 0, 'S'},
     407              :     {"resync-header", no_argument, 0, 'R'},
     408              :     {"verbose", no_argument, 0, 'v'},
     409              :     {0, 0, 0, 0}};
     410              : 
     411              : /** @brief Parses the application arguments
     412              :  *
     413              :  * The arguments are parsed and saved in static structure for future use.
     414              :  *
     415              :  * @param argc The amount of arguments
     416              :  * @param argv The table of arguments
     417              :  *
     418              :  * @return 0 on success, -1 otherwise
     419              :  */
     420            1 : static int parse_args(int argc, char* argv[])
     421              : {
     422              :     int c = -1;
     423            1 :     int long_index = 0;
     424              : 
     425            3 :     while ((c = getopt_long(argc, argv, ":s::t:hSRe:p:d::c:vC:", long_options, &long_index)) != -1)
     426            2 :         switch (c) {
     427            1 :         case 's':
     428            1 :             set_default_event_type(EVENT_SYNC_CACHE);
     429              : 
     430            1 :             if ((optarg != NULL) && (strlen(optarg) >= DLT_MOUNT_PATH_MAX)) {
     431            0 :                 pr_error("Mount path '%s' too long\n", optarg);
     432            0 :                 return -1;
     433              :             }
     434              : 
     435            1 :             set_default_path(optarg);
     436            1 :             break;
     437            0 :         case 't':
     438            0 :             if (optarg != NULL)
     439            0 :                 set_timeout((int)strtol(optarg, NULL, 10));
     440              :             break;
     441            0 :         case 'S': {
     442            0 :             set_send_serial_header(1);
     443            0 :             break;
     444              :         }
     445            0 :         case 'R': {
     446            0 :             set_resync_serial_header(1);
     447            0 :             break;
     448              :         }
     449            0 :         case 'h':
     450            0 :             usage();
     451            0 :             return -1;
     452            0 :         case 'e':
     453            0 :             set_ecuid(optarg);
     454            0 :             break;
     455            0 :         case 'd':
     456            0 :             pr_verbose("Choosing handler.\n");
     457            0 :             set_handler_type(optarg);
     458            0 :             pr_verbose("Handler chosen: %d.\n", get_handler_type());
     459              :             break;
     460            0 :         case 'p':
     461              : 
     462            0 :             if ((optarg != NULL) && (strlen(optarg) >= DLT_MOUNT_PATH_MAX)) {
     463            0 :                 pr_error("Mount path '%s' too long\n", optarg);
     464            0 :                 return -1;
     465              :             }
     466              : 
     467            0 :             set_default_path(optarg);
     468            0 :             break;
     469            0 :         case 'c':
     470            0 :             if (optarg != NULL)
     471            0 :                 set_default_event_type(strtol(optarg, NULL, 10));
     472              :             break;
     473            0 :         case 'v':
     474            0 :             set_verbosity(1);
     475            0 :             pr_verbose("Now in verbose mode.\n");
     476              :             break;
     477            1 :         case 'C':
     478            1 :             set_conf(optarg);
     479            1 :             pr_verbose("Set %s to read options\n", optarg);
     480              :             break;
     481            0 :         case ':':
     482            0 :             pr_error("Option -%c requires an argument.\n", optopt);
     483            0 :             usage();
     484            0 :             return -1;
     485            0 :         case '?':
     486              : 
     487            0 :             if (isprint(optopt))
     488            0 :                 pr_error("Unknown option -%c.\n", optopt);
     489              :             else
     490            0 :                 pr_error("Unknown option character \\x%x.\n", optopt);
     491              : 
     492            0 :             usage();
     493            0 :             return -1;
     494            0 :         default:
     495            0 :             pr_error("Try %s -h for more information.\n", argv[0]);
     496            0 :             return -1;
     497              :         }
     498              : 
     499              : 
     500              : 
     501            1 :     if ((get_default_event_type() == EVENT_SYNC_CACHE) && (get_handler_type() != CTRL_NOHANDLER)) {
     502            0 :         pr_error("Sync caches not available in daemon mode\n");
     503            0 :         return -1;
     504              :     }
     505              : 
     506              :     /* Retrieve ECUID from dlt.conf */
     507            1 :     if (get_ecuid() == NULL)
     508            0 :         set_ecuid(NULL);
     509              : 
     510              :     return 0;
     511              : }
     512              : 
     513              : #if !defined(DLT_SYSTEMD_ENABLE)
     514            0 : int sd_notify(int unset_environment, char* state)
     515              : {
     516              :     /* Satisfy Compiler for warnings */
     517              :     (void)unset_environment;
     518              :     (void)state;
     519            0 :     return 0;
     520              : }
     521              : #endif
     522              : 
     523              : /** @brief Entry point
     524              :  *
     525              :  * Execute the argument parser and call the main feature accordingly.
     526              :  *
     527              :  * @param argc The amount of arguments
     528              :  * @param argv The table of arguments
     529              :  *
     530              :  * @return 0 on success, -1 otherwise
     531              :  */
     532            1 : int main(int argc, char* argv[])
     533              : {
     534              :     int ret = 0;
     535              : 
     536            1 :     set_timeout(DLT_CTRL_TIMEOUT);
     537            1 :     set_send_serial_header(0);
     538            1 :     set_resync_serial_header(0);
     539              : 
     540              :     /* Get command line arguments */
     541            1 :     if (parse_args(argc, argv) != 0)
     542              :         return -1;
     543              : 
     544              :     /* all parameter valid, start communication with daemon or setup
     545              :      * communication with control daemon */
     546            1 :     if (get_handler_type() == CTRL_NOHANDLER) {
     547            1 :         pr_verbose("One shot.\n");
     548              : 
     549            1 :         ret = dlt_logstorage_ctrl_single_request();
     550              : 
     551            1 :         if (ret < 0)
     552            0 :             pr_error("Message failed to be send. Please check DLT config.\n");
     553              :     } else {
     554            0 :         pr_verbose("Entering in daemon mode.\n");
     555              : 
     556              :         /* Let's daemonize */
     557              :         if (sd_notify(0, "READY=1") <= 0) {
     558            0 :             pr_verbose("SD notify failed, manually daemonizing.\n");
     559              : 
     560              :             /* No message can be sent or Systemd is not available.
     561              :              * Daemonizing manually.
     562              :              */
     563              : 
     564              :             // This does the same thing as daemon(1, 1) but is not deprecated
     565            0 :             pid_t pid = fork();
     566            0 :             if (pid < 0) {
     567            0 :                 pr_error("Failed to fork: %s\n", strerror(errno));
     568            0 :                 return EXIT_FAILURE;
     569              :             }
     570            0 :             if (pid > 0) {
     571              :                 /* Parent exits */
     572            0 :                 _exit(EXIT_SUCCESS);
     573              :             }
     574              :             /* Child continues, create new session */
     575            0 :             if (setsid() < 0) {
     576            0 :                 pr_error("Failed to create new session: %s\n", strerror(errno));
     577            0 :                 return EXIT_FAILURE;
     578              :             }
     579              :         }
     580              : 
     581            0 :         pr_verbose("Executing the event loop\n");
     582            0 :         ret = dlt_logstorage_ctrl_setup_event_loop();
     583              :     }
     584              : 
     585            1 :     pr_verbose("Exiting.\n");
     586              :     return ret;
     587              : }
        

Generated by: LCOV version 2.0-1