Terminate the daemon if it's not needed 46/268246/3
authorMateusz Majewski <m.majewski2@samsung.com>
Thu, 16 Dec 2021 12:41:27 +0000 (13:41 +0100)
committerMateusz Majewski <m.majewski2@samsung.com>
Mon, 20 Dec 2021 08:29:07 +0000 (09:29 +0100)
Change-Id: Icf8d83ff134ea84c8aa3c7a869bd8394f6c2685e

configs/dlog-logger.conf.qos
configs/dlog-pipe.conf.qos
configs/dlog_logger.service.in
src/logger/logger.c
tests/dlog_test.in

index 5820f27..5de92b8 100644 (file)
@@ -36,6 +36,10 @@ util_sorting_time_window=1000
 util_sorting_buffer_size=8192
 dynamic_config_path=/tmp/dlog-filters/
 
+dlog_logger_conf_test0=dlogutil -b main -r 512 -n 10 -f /var/lib/dlog-tests/test0 -v threadtime *:I
+dlog_logger_conf_test1=dlogutil -b main -r 512 -n 10 -f /var/lib/dlog-tests/test1 -v threadtime
+dlog_logger_conf_test2=dlogutil -b main -r 512 -n 10 -f /var/lib/dlog-tests/test2 -v threadtime *:E
+
 qos_file_path=/tmp/dlog-filters/42-qos.conf
 qos_refresh_rate_s=5
 qos_max_throughput_logs=50
index dbc99e2..d9e2bd4 100644 (file)
@@ -84,6 +84,10 @@ radio_size=1048576
 kmsg_size=1048576
 syslog_size=1048576
 
+dlog_logger_conf_test0=dlogutil -b main -r 512 -n 10 -f /var/lib/dlog-tests/test0 -v threadtime *:I
+dlog_logger_conf_test1=dlogutil -b main -r 512 -n 10 -f /var/lib/dlog-tests/test1 -v threadtime
+dlog_logger_conf_test2=dlogutil -b main -r 512 -n 10 -f /var/lib/dlog-tests/test2 -v threadtime *:E
+
 util_sorting_time_window=5000
 util_sorting_buffer_size=32000
 dynamic_config_path=/tmp/dlog-filters/
index 7b3c493..285d101 100644 (file)
@@ -32,7 +32,7 @@ SmackProcessLabel=System
 ExecStart=/usr/bin/dlog_logger
 Capabilities=cap_syslog=i
 SecureBits=keep-caps
-Restart=always
+Restart=on-failure
 LimitNOFILE=16384
 Nice=1
 
index 5d89099..6427c3e 100644 (file)
@@ -1285,6 +1285,40 @@ static void precreate_logctl_file(struct logger_config_data *data)
        close(fd);
 }
 
+bool early_termination(const struct logger_config_data *data, const struct logger *logger) {
+       /* In order to check if the deamon will be doing nothing
+        * and can quit instantaneously, we do three checks: */
+
+       /* 1. We make sure that there are no logger subreaders.
+        * When the logger backend is being used, the daemon reads the data
+        * in order to use it internally. The daemon always reads each buffer
+        * to a separate reader and each concrete usage has its own subreader.
+        * Therefore, we need to check if no subreaders exist. */
+       for (list_head l = logger->readers_logger; l != NULL; list_next(&l)) {
+               struct reader_logger *reader = list_at(l);
+               if (reader->subs != NULL)
+                       return false;
+       }
+
+       /* 2. We make sure that no pipe-like buffer is enabled.
+        * When the pipe backend is being used or pipe-like buffers
+        * (i.e. KMSG, SYSLOG) are handled, the logger allocates space for them.
+        * In this case, we cannot terminate even if the buffer is enabled
+        * but unused at the moment, since it might be connected to
+        * (for instance by dlogutil). */
+       for (log_id_t id = 0; id < LOG_ID_MAX; id++)
+               if (data->is_buffer_enabled[id])
+                       return false;
+
+       /* 3. We make sure that there are no writers.
+        * In theory, previous checks are sufficient.
+        * However, we do another check just to be sure
+        * (since if there are writers, we shouldn't terminate).
+        * Additionally, this could change in the future,
+        * so let's hedge against someone forgetting that this function exists. */
+       return logger->writers == NULL;
+}
+
 /**
  * @brief The logger
  * @return 0 on success, nonzero on failure
@@ -1341,6 +1375,12 @@ int main(int argc, char **argv)
                goto cleanup;
        }
 
+       if (early_termination(&data, &server)) {
+               printf("No work to do. Exiting.\n");
+               ret = DLOG_EXIT_SUCCESS;
+               goto cleanup;
+       }
+
        if ((r = do_logger(&server)) < 0) {
                errno = -r;
                printf("Runtime failure (%m). Exiting.\n");
index 98d7cfc..359273a 100644 (file)
@@ -167,6 +167,51 @@ PATH=$PATH:@libexecdir@/libdlog/
 RUNTIME_FILTERS_DIR="/tmp/dlog-filters/"
 mkdir -p "$RUNTIME_FILTERS_DIR"
 
+PREEARLYQUIT_CONFIG_PATH="$DLOG_CONFIG_PATH"
+DLOG_CONFIG_PATH="$TESTDIR/earlyquit.conf"
+if [ "$quick" -ne 1 ]; then
+       for PERSISTENT in 1 0; do
+       for KMSG in 1 0; do
+       for SYSLOG in 1 0; do
+       for QOS in 1 0; do
+               # TODO: Does syslog even work? Disabling for now.
+               [ "$SYSLOG" -eq 1 ] && continue
+
+               if [ "$QOS" -eq 1 ]; then
+                       SOURCE="@datadir@/dlog-$type.conf.qos"
+               else
+                       SOURCE="@datadir@/dlog-$type.conf.test"
+               fi
+
+               if [ "$PERSISTENT" -eq 1 ]; then
+                       cp "$SOURCE" "$DLOG_CONFIG_PATH"
+               else
+                       sed 's/^dlog_logger_conf.*$/#\0/' <"$SOURCE" >"$DLOG_CONFIG_PATH"
+               fi
+
+               echo "handle_kmsg=$KMSG" >> "$DLOG_CONFIG_PATH"
+               echo "syslog_force=$SYSLOG" >> "$DLOG_CONFIG_PATH"
+
+               dlog_logger -t 0 &
+               LOGGER=$!
+               sleep 1
+
+               kill $LOGGER > /dev/null
+               STOPPED=$?
+               LOGGER=-1
+
+               if [ "$PERSISTENT" -eq 0 ] && [ "$KMSG" -eq 0 ] && [ "$SYSLOG" -eq 0 ] && [ "$QOS" -eq 0 ] && [ "$type" = "logger" ]; then
+                       EXPECTED=1
+               else
+                       EXPECTED=0
+               fi
+
+               LOG_DETAILS="testing if daemon stops when not needed (persistent=$PERSISTENT, kmsg=$KMSG, syslog=$SYSLOG, qos=$QOS)"
+               [ "$STOPPED" -eq "$EXPECTED" ] && ok || fail
+       done; done; done; done
+fi
+DLOG_CONFIG_PATH="$PREEARLYQUIT_CONFIG_PATH"
+
 # Start the daemon
 dlog_logger -t 0 &
 LOGGER=$!