[Pkg-sssd-devel] sssd: Changes to 'ubuntu-trusty'

Victor Tapia King victortapia-guest at moszumanska.debian.org
Sun Apr 16 19:39:22 UTC 2017


 debian/changelog                                    |    4 
 debian/patches/BUILD-Fix-linking-with-librt.diff    |   50 --
 debian/patches/BUILD-Fix-linking-with-librt.patch   |   50 ++
 debian/patches/restart_providers_on_timeshift.diff  |  406 --------------------
 debian/patches/restart_providers_on_timeshift.patch |  406 ++++++++++++++++++++
 debian/patches/series                               |    4 
 6 files changed, 460 insertions(+), 460 deletions(-)

New commits:
commit 693a35122eb21c439302ab8811fb91c4607d865e
Author: Victor Tapia <victor.tapia at canonical.com>
Date:   Sun Apr 16 21:35:42 2017 +0200

    Fixed patch files extensions for Ubuntu
    - d/p/restart_providers_on_timeshift.diff and BUILD-Fix-linking-with-librt.diff
      were uploaded to Ubuntu as .patch. To avoid further issues uploading, set
      the same extension here.

diff --git a/debian/changelog b/debian/changelog
index 381ee70..3cf7b51 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -9,7 +9,7 @@ sssd (1.11.8-0ubuntu0.6) trusty; urgency=medium
 
 sssd (1.11.8-0ubuntu0.5) trusty; urgency=medium
 
-  * d/p/BUILD-Fix-linking-with-librt.diff: Upstream fix for FTBS on
+  * d/p/BUILD-Fix-linking-with-librt.patch: Upstream fix for FTBS on
     ppc64el/arm64 after the implementation of timer functions in watchdog
     (LP: #1641875).
 
@@ -17,7 +17,7 @@ sssd (1.11.8-0ubuntu0.5) trusty; urgency=medium
 
 sssd (1.11.8-0ubuntu0.4) trusty; urgency=medium
 
-  * d/p/restart_providers_on_timeshift.diff: Implement watchdog and
+  * d/p/restart_providers_on_timeshift.patch: Implement watchdog and
     use SIGUSR2 after watchdog detects time shift to execute pending
     scheduled tasks that could be stuck (LP: #1641875)
 
diff --git a/debian/patches/BUILD-Fix-linking-with-librt.diff b/debian/patches/BUILD-Fix-linking-with-librt.diff
deleted file mode 100644
index c34edd9..0000000
--- a/debian/patches/BUILD-Fix-linking-with-librt.diff
+++ /dev/null
@@ -1,50 +0,0 @@
-From dc416984d92890f31122d32240d8bc0cbf48a48e Mon Sep 17 00:00:00 2001
-From: Lukas Slebodnik <lslebodn at redhat.com>
-Date: Mon, 7 Nov 2016 11:53:21 +0100
-Subject: [PATCH] BUILD: Fix linking with librt
-
-The posix realime extensions defines timer_* functions
-but it does not mention library with these functions.
-http://www.unix.org/version2/whatsnew/realtime.html
-
-The autoconf macro AC_SEARCH_LIBS firstly check the function
-timer_create with no libraries, then for each library listed
-in 2nd parameter. Possible libraries librt and libposix4
-were used in nspr for similar detection.
----
- Makefile.am  |  1 +
- configure.ac | 13 +++++++++++++
- 2 files changed, 14 insertions(+)
-
---- a/Makefile.am
-+++ b/Makefile.am
-@@ -623,6 +623,7 @@
-     $(AM_CFLAGS) \
-     $(SYSTEMD_LOGIN_CFLAGS)
- libsss_util_la_LIBADD = \
-+    $(LIBADD_TIMER) \
-     $(SSSD_LIBS) \
-     $(UNICODE_LIBS)
- if BUILD_SUDO
---- a/configure.ac
-+++ b/configure.ac
-@@ -64,6 +64,19 @@
-                  pthread_mutex_consistent_np ])
- LIBS=$SAVE_LIBS
- 
-+# Check library for the timer_create function
-+SAVE_LIBS=$LIBS
-+LIBS=
-+LIBADD_TIMER=
-+AC_SEARCH_LIBS([timer_create], [rt posix4],
-+    [AC_DEFINE([HAVE_LIBRT], [1],
-+         [Define if you have the librt library or equivalent.])
-+     LIBADD_TIMER="$LIBS"],
-+    [AC_MSG_ERROR([unable to find library fot the timer_create() function])])
-+
-+AC_SUBST([LIBADD_TIMER])
-+LIBS=$SAVE_LIBS
-+
- # Check for presence of modern functions for setting file timestamps
- AC_CHECK_FUNCS([ utimensat \
-                  futimens ])
diff --git a/debian/patches/BUILD-Fix-linking-with-librt.patch b/debian/patches/BUILD-Fix-linking-with-librt.patch
new file mode 100644
index 0000000..c34edd9
--- /dev/null
+++ b/debian/patches/BUILD-Fix-linking-with-librt.patch
@@ -0,0 +1,50 @@
+From dc416984d92890f31122d32240d8bc0cbf48a48e Mon Sep 17 00:00:00 2001
+From: Lukas Slebodnik <lslebodn at redhat.com>
+Date: Mon, 7 Nov 2016 11:53:21 +0100
+Subject: [PATCH] BUILD: Fix linking with librt
+
+The posix realime extensions defines timer_* functions
+but it does not mention library with these functions.
+http://www.unix.org/version2/whatsnew/realtime.html
+
+The autoconf macro AC_SEARCH_LIBS firstly check the function
+timer_create with no libraries, then for each library listed
+in 2nd parameter. Possible libraries librt and libposix4
+were used in nspr for similar detection.
+---
+ Makefile.am  |  1 +
+ configure.ac | 13 +++++++++++++
+ 2 files changed, 14 insertions(+)
+
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -623,6 +623,7 @@
+     $(AM_CFLAGS) \
+     $(SYSTEMD_LOGIN_CFLAGS)
+ libsss_util_la_LIBADD = \
++    $(LIBADD_TIMER) \
+     $(SSSD_LIBS) \
+     $(UNICODE_LIBS)
+ if BUILD_SUDO
+--- a/configure.ac
++++ b/configure.ac
+@@ -64,6 +64,19 @@
+                  pthread_mutex_consistent_np ])
+ LIBS=$SAVE_LIBS
+ 
++# Check library for the timer_create function
++SAVE_LIBS=$LIBS
++LIBS=
++LIBADD_TIMER=
++AC_SEARCH_LIBS([timer_create], [rt posix4],
++    [AC_DEFINE([HAVE_LIBRT], [1],
++         [Define if you have the librt library or equivalent.])
++     LIBADD_TIMER="$LIBS"],
++    [AC_MSG_ERROR([unable to find library fot the timer_create() function])])
++
++AC_SUBST([LIBADD_TIMER])
++LIBS=$SAVE_LIBS
++
+ # Check for presence of modern functions for setting file timestamps
+ AC_CHECK_FUNCS([ utimensat \
+                  futimens ])
diff --git a/debian/patches/restart_providers_on_timeshift.diff b/debian/patches/restart_providers_on_timeshift.diff
deleted file mode 100644
index 3884e81..0000000
--- a/debian/patches/restart_providers_on_timeshift.diff
+++ /dev/null
@@ -1,406 +0,0 @@
-Description: Restart the providers after a time shift has been detected
- This patch implements the watchdog from upstream and restarts the providers
- using the already implemented SIGUSR2 for method .resetOffline (used after
- netlink detects an interface change). By doing this, events like LDAP
- connection retries will be executed immediately instead of having to wait
- the time shifted (potentially hours) to get to its normal schedule.
-
-Author: Victor Tapia <victor.tapia at canonical.com>
-Bug: https://fedorahosted.org/sssd/ticket/3285
-Bug-Ubuntu: https://bugs.launchpad.net/bugs/1641875
-Last-Update: 2017-02-15
-
---- a/Makefile.am
-+++ b/Makefile.am
-@@ -617,6 +617,7 @@
-     src/util/io.c \
-     src/util/util_sss_idmap.c \
-     src/util/string_utils.c \
-+    src/util/util_watchdog.c \
-     $(NULL)
- libsss_util_la_CFLAGS = \
-     $(AM_CFLAGS) \
---- a/src/monitor/monitor.c
-+++ b/src/monitor/monitor.c
-@@ -2805,6 +2805,8 @@
- 
-     /* we want a pid file check */
-     flags |= FLAGS_PID_FILE;
-+    /* the monitor should not run a watchdog on itself */
-+    flags |= FLAGS_NO_WATCHDOG;
- 
-     /* Open before server_setup() does to have logging
-      * during configuration checking */
---- a/src/util/server.c
-+++ b/src/util/server.c
-@@ -415,6 +415,7 @@
-     bool dm;
-     struct tevent_signal *tes;
-     struct logrotate_ctx *lctx;
-+    int watchdog_interval;
- 
-     debug_prg_name = strdup(name);
-     if (!debug_prg_name) {
-@@ -571,6 +572,24 @@
-             return ret;
-         }
-     }
-+
-+    /* Setup the internal watchdog */
-+    ret = confdb_get_int(ctx->confdb_ctx, conf_entry,
-+                         CONFDB_DOMAIN_TIMEOUT,
-+                         0, &watchdog_interval);
-+    if (ret != EOK) {
-+        DEBUG(SSSDBG_FATAL_FAILURE, "Error reading from confdb (%d) [%s]\n",
-+                                     ret, strerror(ret));
-+        return ret;
-+    }
-+
-+    if ((flags & FLAGS_NO_WATCHDOG) == 0) {
-+        ret = setup_watchdog(ctx->event_ctx, watchdog_interval);
-+        if (ret != EOK) {
-+            DEBUG(SSSDBG_CRIT_FAILURE, "Watchdog setup failed.\n");
-+            return ret;
-+        }
-+    }
- 
-     sss_log(SSS_LOG_INFO, "Starting up");
- 
---- a/src/util/util.h
-+++ b/src/util/util.h
-@@ -26,6 +26,7 @@
- #include <stdint.h>
- #include <stdbool.h>
- #include <unistd.h>
-+#include <fcntl.h>
- #include <string.h>
- #include <strings.h>
- #include <ctype.h>
-@@ -158,6 +159,21 @@
- #define FLAGS_DAEMON 0x0001
- #define FLAGS_INTERACTIVE 0x0002
- #define FLAGS_PID_FILE 0x0004
-+#define FLAGS_NO_WATCHDOG 0x0010
-+
-+#define PIPE_INIT { -1, -1 }
-+
-+#define PIPE_FD_CLOSE(fd) do {      \
-+    if (fd != -1) {                 \
-+        close(fd);                  \
-+        fd = -1;                    \
-+    }                               \
-+} while(0);
-+
-+#define PIPE_CLOSE(p) do {          \
-+    PIPE_FD_CLOSE(p[0]);            \
-+    PIPE_FD_CLOSE(p[1]);            \
-+} while(0);
- 
- #ifndef talloc_zfree
- #define talloc_zfree(ptr) do { talloc_free(discard_const(ptr)); ptr = NULL; } while(0)
-@@ -541,4 +557,19 @@
-                                  const char *orig_name,
-                                  const char replace_char);
- 
-+/**
-+ * @brief set file descriptor as nonblocking
-+ *
-+ * Set the O_NONBLOCK flag for the input fd
-+ *
-+ * @param[in] fd            The file descriptor to set as nonblocking
-+ *
-+ * @return                  EOK on success, errno code otherwise
-+ */
-+errno_t sss_fd_nonblocking(int fd);
-+
-+/* from util_watchdog.c */
-+int setup_watchdog(struct tevent_context *ev, int interval);
-+void teardown_watchdog(void);
-+
- #endif /* __SSSD_UTIL_H__ */
---- a/src/util/util.c
-+++ b/src/util/util.c
-@@ -749,3 +749,27 @@
- 
-     return false;
- }
-+
-+/* Set the nonblocking flag to the fd */
-+errno_t sss_fd_nonblocking(int fd)
-+{
-+    int flags;
-+    int ret;
-+
-+    flags = fcntl(fd, F_GETFL, 0);
-+    if (flags == -1) {
-+        ret = errno;
-+        DEBUG(SSSDBG_CRIT_FAILURE,
-+              "F_GETFL failed [%d][%s].\n", ret, strerror(ret));
-+        return ret;
-+    }
-+
-+    if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) {
-+        ret = errno;
-+        DEBUG(SSSDBG_CRIT_FAILURE,
-+              "F_SETFL failed [%d][%s].\n", ret, strerror(ret));
-+        return ret;
-+    }
-+
-+    return EOK;
-+}
---- /dev/null
-+++ b/src/util/util_watchdog.c
-@@ -0,0 +1,253 @@
-+/*
-+   SSSD
-+
-+   Timer Watchdog routines
-+
-+   Copyright (C) Simo Sorce             2016
-+
-+   This program is free software; you can redistribute it and/or modify
-+   it under the terms of the GNU General Public License as published by
-+   the Free Software Foundation; either version 3 of the License, or
-+   (at your option) any later version.
-+
-+   This program is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+   GNU General Public License for more details.
-+
-+   You should have received a copy of the GNU General Public License
-+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-+*/
-+
-+#include "util/util.h"
-+
-+#define WATCHDOG_DEF_INTERVAL 10
-+#define WATCHDOG_MAX_TICKS 3
-+#define DEFAULT_BUFFER_SIZE 4096
-+
-+/* this is intentionally a global variable */
-+struct watchdog_ctx {
-+    timer_t timerid;
-+    struct timeval interval;
-+    struct tevent_timer *te;
-+    volatile int ticks;
-+
-+    /* To detect time shift. */
-+    struct tevent_context *ev;
-+    int input_interval;
-+    time_t timestamp;
-+    struct tevent_fd *tfd;
-+    int pipefd[2];
-+} watchdog_ctx;
-+
-+static void watchdog_detect_timeshift(void)
-+{
-+    time_t prev_time;
-+    time_t cur_time;
-+
-+    prev_time = watchdog_ctx.timestamp;
-+    cur_time = watchdog_ctx.timestamp = time(NULL);
-+    if (cur_time < prev_time) {
-+        /* Time shift detected. We need to restart watchdog. */
-+        if (write(watchdog_ctx.pipefd[1], "1", 1) != 1) {
-+            if (getpid() == getpgrp()) {
-+                kill(-getpgrp(), SIGTERM);
-+            } else {
-+                _exit(1);
-+            }
-+        }
-+    }
-+}
-+
-+/* the watchdog is purposefully *not* handled by the tevent
-+ * signal handler as it is meant to check if the daemon is
-+ * still processing the event queue itself. A stuck process
-+ * may not handle the event queue at all and thus not handle
-+ * signals either */
-+static void watchdog_handler(int sig)
-+{
-+
-+    watchdog_detect_timeshift();
-+
-+    /* if a pre-defined number of ticks passed by kills itself */
-+    if (__sync_add_and_fetch(&watchdog_ctx.ticks, 1) > WATCHDOG_MAX_TICKS) {
-+        if (getpid() == getpgrp()) {
-+            kill(-getpgrp(), SIGTERM);
-+        } else {
-+            _exit(1);
-+        }
-+    }
-+}
-+
-+static void watchdog_reset(void)
-+{
-+    __sync_and_and_fetch(&watchdog_ctx.ticks, 0);
-+}
-+
-+static void watchdog_event_handler(struct tevent_context *ev,
-+                                   struct tevent_timer *te,
-+                                   struct timeval current_time,
-+                                   void *private_data)
-+{
-+    /* first thing reset the watchdog ticks */
-+    watchdog_reset();
-+
-+    /* then set a new watchodg event */
-+    watchdog_ctx.te = tevent_add_timer(ev, ev,
-+        tevent_timeval_current_ofs(watchdog_ctx.interval.tv_sec, 0),
-+        watchdog_event_handler, NULL);
-+    /* if the function fails the watchdog will kill the
-+     * process soon enough, so we just warn */
-+    if (!watchdog_ctx.te) {
-+        DEBUG(SSSDBG_FATAL_FAILURE,
-+              "Failed to create a watchdog timer event!\n");
-+    }
-+}
-+
-+static errno_t watchdog_fd_recv_data(int fd)
-+{
-+    ssize_t len;
-+    char buffer[DEFAULT_BUFFER_SIZE];
-+    errno_t ret;
-+
-+    errno = 0;
-+    len = read(fd, buffer, DEFAULT_BUFFER_SIZE);
-+    if (len == -1) {
-+        if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) {
-+            return EAGAIN;
-+        } else {
-+            ret = errno;
-+            DEBUG(SSSDBG_CRIT_FAILURE,
-+                  "write failed [%d]: %s\n", ret, strerror(ret));
-+            return ret;
-+        }
-+    }
-+
-+    return EOK;
-+}
-+
-+static void watchdog_fd_read_handler(struct tevent_context *ev,
-+                                     struct tevent_fd *fde,
-+                                     uint16_t flags,
-+                                     void *data)
-+{
-+    errno_t ret;
-+
-+    ret = watchdog_fd_recv_data(watchdog_ctx.pipefd[0]);
-+    switch(ret) {
-+    case EAGAIN:
-+        DEBUG(SSSDBG_TRACE_ALL,
-+              "Interrupted before any data could be read, retry later.\n");
-+        return;
-+    case EOK:
-+        /* all fine */
-+        break;
-+    default:
-+        DEBUG(SSSDBG_FATAL_FAILURE,
-+              "Failed to receive data [%d]: %s. "
-+              "sig_term() will be called.\n", ret, strerror(ret));
-+        sig_term(1);
-+    }
-+
-+    DEBUG(SSSDBG_IMPORTANT_INFO, "Time shift detected, "
-+          "restarting watchdog!\n");
-+    if (getpid() == getpgrp()) {
-+        kill(-getpgrp(), SIGUSR2);
-+    }
-+}
-+
-+int setup_watchdog(struct tevent_context *ev, int interval)
-+{
-+    struct sigevent sev;
-+    struct itimerspec its;
-+    struct tevent_fd *tfd;
-+    int signum = SIGRTMIN;
-+    int ret;
-+
-+    ZERO_STRUCT(sev);
-+    CatchSignal(signum, watchdog_handler);
-+
-+    sev.sigev_notify = SIGEV_SIGNAL;
-+    sev.sigev_signo = signum;
-+    sev.sigev_value.sival_ptr = &watchdog_ctx.timerid;
-+    errno = 0;
-+    ret = timer_create(CLOCK_MONOTONIC, &sev, &watchdog_ctx.timerid);
-+    if (ret == -1) {
-+        ret = errno;
-+        DEBUG(SSSDBG_FATAL_FAILURE,
-+              "Failed to create watchdog timer (%d) [%s]\n",
-+              ret, strerror(ret));
-+        return ret;
-+    }
-+
-+    if (interval == 0) {
-+        interval = WATCHDOG_DEF_INTERVAL;
-+    }
-+    watchdog_ctx.interval.tv_sec = interval;
-+    watchdog_ctx.interval.tv_usec = 0;
-+
-+    watchdog_ctx.ev = ev;
-+    watchdog_ctx.input_interval = interval;
-+    watchdog_ctx.timestamp = time(NULL);
-+
-+    ret = pipe(watchdog_ctx.pipefd);
-+    if (ret == -1) {
-+        ret = errno;
-+        DEBUG(SSSDBG_FATAL_FAILURE,
-+              "pipe failed [%d] [%s].\n", ret, strerror(ret));
-+        return ret;
-+    }
-+
-+    sss_fd_nonblocking(watchdog_ctx.pipefd[0]);
-+    sss_fd_nonblocking(watchdog_ctx.pipefd[1]);
-+
-+    tfd = tevent_add_fd(ev, (TALLOC_CTX *)ev, watchdog_ctx.pipefd[0],
-+                        TEVENT_FD_READ, watchdog_fd_read_handler, NULL);
-+    watchdog_ctx.tfd = tfd;
-+
-+    /* Start the timer */
-+    /* we give 1 second head start to the watchdog event */
-+    its.it_value.tv_sec = interval + 1;
-+    its.it_value.tv_nsec = 0;
-+    its.it_interval.tv_sec = interval;
-+    its.it_interval.tv_nsec = 0;
-+    errno = 0;
-+    ret = timer_settime(watchdog_ctx.timerid, 0, &its, NULL);
-+    if (ret == -1) {
-+        ret = errno;
-+        DEBUG(SSSDBG_FATAL_FAILURE,
-+              "Failed to create watchdog timer (%d) [%s]\n",
-+              ret, strerror(ret));
-+        return ret;
-+    }
-+
-+    /* Add the watchdog event and make it fire as fast as the timer */
-+    watchdog_event_handler(ev, NULL, tevent_timeval_zero(), NULL);
-+
-+    return EOK;
-+}
-+
-+void teardown_watchdog(void)
-+{
-+    int ret;
-+
-+    /* Disarm the timer */
-+    errno = 0;
-+    ret = timer_delete(watchdog_ctx.timerid);
-+    if (ret == -1) {
-+        ret = errno;
-+        DEBUG(SSSDBG_FATAL_FAILURE,
-+              "Failed to destroy watchdog timer (%d) [%s]\n",
-+             ret, strerror(ret));
-+    }
-+
-+    /* Free the tevent_fd */
-+    talloc_zfree(watchdog_ctx.tfd);
-+
-+    /* Close the pipefds */
-+    PIPE_FD_CLOSE(watchdog_ctx.pipefd[0]);
-+    PIPE_FD_CLOSE(watchdog_ctx.pipefd[1]);
-+
-+    /* and kill the watchdog event */
-+    talloc_free(watchdog_ctx.te);
-+}
diff --git a/debian/patches/restart_providers_on_timeshift.patch b/debian/patches/restart_providers_on_timeshift.patch
new file mode 100644
index 0000000..3884e81
--- /dev/null
+++ b/debian/patches/restart_providers_on_timeshift.patch
@@ -0,0 +1,406 @@
+Description: Restart the providers after a time shift has been detected
+ This patch implements the watchdog from upstream and restarts the providers
+ using the already implemented SIGUSR2 for method .resetOffline (used after
+ netlink detects an interface change). By doing this, events like LDAP
+ connection retries will be executed immediately instead of having to wait
+ the time shifted (potentially hours) to get to its normal schedule.
+
+Author: Victor Tapia <victor.tapia at canonical.com>
+Bug: https://fedorahosted.org/sssd/ticket/3285
+Bug-Ubuntu: https://bugs.launchpad.net/bugs/1641875
+Last-Update: 2017-02-15
+
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -617,6 +617,7 @@
+     src/util/io.c \
+     src/util/util_sss_idmap.c \
+     src/util/string_utils.c \
++    src/util/util_watchdog.c \
+     $(NULL)
+ libsss_util_la_CFLAGS = \
+     $(AM_CFLAGS) \
+--- a/src/monitor/monitor.c
++++ b/src/monitor/monitor.c
+@@ -2805,6 +2805,8 @@
+ 
+     /* we want a pid file check */
+     flags |= FLAGS_PID_FILE;
++    /* the monitor should not run a watchdog on itself */
++    flags |= FLAGS_NO_WATCHDOG;
+ 
+     /* Open before server_setup() does to have logging
+      * during configuration checking */
+--- a/src/util/server.c
++++ b/src/util/server.c
+@@ -415,6 +415,7 @@
+     bool dm;
+     struct tevent_signal *tes;
+     struct logrotate_ctx *lctx;
++    int watchdog_interval;
+ 
+     debug_prg_name = strdup(name);
+     if (!debug_prg_name) {
+@@ -571,6 +572,24 @@
+             return ret;
+         }
+     }
++
++    /* Setup the internal watchdog */
++    ret = confdb_get_int(ctx->confdb_ctx, conf_entry,
++                         CONFDB_DOMAIN_TIMEOUT,
++                         0, &watchdog_interval);
++    if (ret != EOK) {
++        DEBUG(SSSDBG_FATAL_FAILURE, "Error reading from confdb (%d) [%s]\n",
++                                     ret, strerror(ret));
++        return ret;
++    }
++
++    if ((flags & FLAGS_NO_WATCHDOG) == 0) {
++        ret = setup_watchdog(ctx->event_ctx, watchdog_interval);
++        if (ret != EOK) {
++            DEBUG(SSSDBG_CRIT_FAILURE, "Watchdog setup failed.\n");
++            return ret;
++        }
++    }
+ 
+     sss_log(SSS_LOG_INFO, "Starting up");
+ 
+--- a/src/util/util.h
++++ b/src/util/util.h
+@@ -26,6 +26,7 @@
+ #include <stdint.h>
+ #include <stdbool.h>
+ #include <unistd.h>
++#include <fcntl.h>
+ #include <string.h>
+ #include <strings.h>
+ #include <ctype.h>
+@@ -158,6 +159,21 @@
+ #define FLAGS_DAEMON 0x0001
+ #define FLAGS_INTERACTIVE 0x0002
+ #define FLAGS_PID_FILE 0x0004
++#define FLAGS_NO_WATCHDOG 0x0010
++
++#define PIPE_INIT { -1, -1 }
++
++#define PIPE_FD_CLOSE(fd) do {      \
++    if (fd != -1) {                 \
++        close(fd);                  \
++        fd = -1;                    \
++    }                               \
++} while(0);
++
++#define PIPE_CLOSE(p) do {          \
++    PIPE_FD_CLOSE(p[0]);            \
++    PIPE_FD_CLOSE(p[1]);            \
++} while(0);
+ 
+ #ifndef talloc_zfree
+ #define talloc_zfree(ptr) do { talloc_free(discard_const(ptr)); ptr = NULL; } while(0)
+@@ -541,4 +557,19 @@
+                                  const char *orig_name,
+                                  const char replace_char);
+ 
++/**
++ * @brief set file descriptor as nonblocking
++ *
++ * Set the O_NONBLOCK flag for the input fd
++ *
++ * @param[in] fd            The file descriptor to set as nonblocking
++ *
++ * @return                  EOK on success, errno code otherwise
++ */
++errno_t sss_fd_nonblocking(int fd);
++
++/* from util_watchdog.c */
++int setup_watchdog(struct tevent_context *ev, int interval);
++void teardown_watchdog(void);
++
+ #endif /* __SSSD_UTIL_H__ */
+--- a/src/util/util.c
++++ b/src/util/util.c
+@@ -749,3 +749,27 @@
+ 
+     return false;
+ }
++
++/* Set the nonblocking flag to the fd */
++errno_t sss_fd_nonblocking(int fd)
++{
++    int flags;
++    int ret;
++
++    flags = fcntl(fd, F_GETFL, 0);
++    if (flags == -1) {
++        ret = errno;
++        DEBUG(SSSDBG_CRIT_FAILURE,
++              "F_GETFL failed [%d][%s].\n", ret, strerror(ret));
++        return ret;
++    }
++
++    if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) {
++        ret = errno;
++        DEBUG(SSSDBG_CRIT_FAILURE,
++              "F_SETFL failed [%d][%s].\n", ret, strerror(ret));
++        return ret;
++    }
++
++    return EOK;
++}
+--- /dev/null
++++ b/src/util/util_watchdog.c
+@@ -0,0 +1,253 @@
++/*
++   SSSD
++
++   Timer Watchdog routines
++
++   Copyright (C) Simo Sorce             2016
++
++   This program is free software; you can redistribute it and/or modify
++   it under the terms of the GNU General Public License as published by
++   the Free Software Foundation; either version 3 of the License, or
++   (at your option) any later version.
++
++   This program is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++   GNU General Public License for more details.
++
++   You should have received a copy of the GNU General Public License
++   along with this program.  If not, see <http://www.gnu.org/licenses/>.
++*/
++
++#include "util/util.h"
++
++#define WATCHDOG_DEF_INTERVAL 10
++#define WATCHDOG_MAX_TICKS 3
++#define DEFAULT_BUFFER_SIZE 4096
++
++/* this is intentionally a global variable */
++struct watchdog_ctx {
++    timer_t timerid;
++    struct timeval interval;
++    struct tevent_timer *te;
++    volatile int ticks;
++
++    /* To detect time shift. */
++    struct tevent_context *ev;
++    int input_interval;
++    time_t timestamp;
++    struct tevent_fd *tfd;
++    int pipefd[2];
++} watchdog_ctx;
++
++static void watchdog_detect_timeshift(void)
++{
++    time_t prev_time;
++    time_t cur_time;
++
++    prev_time = watchdog_ctx.timestamp;
++    cur_time = watchdog_ctx.timestamp = time(NULL);
++    if (cur_time < prev_time) {
++        /* Time shift detected. We need to restart watchdog. */
++        if (write(watchdog_ctx.pipefd[1], "1", 1) != 1) {
++            if (getpid() == getpgrp()) {
++                kill(-getpgrp(), SIGTERM);
++            } else {
++                _exit(1);
++            }
++        }
++    }
++}
++
++/* the watchdog is purposefully *not* handled by the tevent
++ * signal handler as it is meant to check if the daemon is
++ * still processing the event queue itself. A stuck process
++ * may not handle the event queue at all and thus not handle
++ * signals either */
++static void watchdog_handler(int sig)
++{
++
++    watchdog_detect_timeshift();
++
++    /* if a pre-defined number of ticks passed by kills itself */
++    if (__sync_add_and_fetch(&watchdog_ctx.ticks, 1) > WATCHDOG_MAX_TICKS) {
++        if (getpid() == getpgrp()) {
++            kill(-getpgrp(), SIGTERM);
++        } else {
++            _exit(1);
++        }
++    }
++}
++
++static void watchdog_reset(void)
++{
++    __sync_and_and_fetch(&watchdog_ctx.ticks, 0);
++}
++
++static void watchdog_event_handler(struct tevent_context *ev,
++                                   struct tevent_timer *te,
++                                   struct timeval current_time,
++                                   void *private_data)
++{
++    /* first thing reset the watchdog ticks */
++    watchdog_reset();
++
++    /* then set a new watchodg event */
++    watchdog_ctx.te = tevent_add_timer(ev, ev,
++        tevent_timeval_current_ofs(watchdog_ctx.interval.tv_sec, 0),
++        watchdog_event_handler, NULL);
++    /* if the function fails the watchdog will kill the
++     * process soon enough, so we just warn */
++    if (!watchdog_ctx.te) {
++        DEBUG(SSSDBG_FATAL_FAILURE,
++              "Failed to create a watchdog timer event!\n");
++    }
++}
++
++static errno_t watchdog_fd_recv_data(int fd)
++{
++    ssize_t len;
++    char buffer[DEFAULT_BUFFER_SIZE];
++    errno_t ret;
++
++    errno = 0;
++    len = read(fd, buffer, DEFAULT_BUFFER_SIZE);
++    if (len == -1) {
++        if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) {
++            return EAGAIN;
++        } else {
++            ret = errno;
++            DEBUG(SSSDBG_CRIT_FAILURE,
++                  "write failed [%d]: %s\n", ret, strerror(ret));
++            return ret;
++        }
++    }
++
++    return EOK;
++}
++
++static void watchdog_fd_read_handler(struct tevent_context *ev,
++                                     struct tevent_fd *fde,
++                                     uint16_t flags,
++                                     void *data)
++{
++    errno_t ret;
++
++    ret = watchdog_fd_recv_data(watchdog_ctx.pipefd[0]);
++    switch(ret) {
++    case EAGAIN:
++        DEBUG(SSSDBG_TRACE_ALL,
++              "Interrupted before any data could be read, retry later.\n");
++        return;
++    case EOK:
++        /* all fine */
++        break;
++    default:
++        DEBUG(SSSDBG_FATAL_FAILURE,
++              "Failed to receive data [%d]: %s. "
++              "sig_term() will be called.\n", ret, strerror(ret));
++        sig_term(1);
++    }
++
++    DEBUG(SSSDBG_IMPORTANT_INFO, "Time shift detected, "
++          "restarting watchdog!\n");
++    if (getpid() == getpgrp()) {
++        kill(-getpgrp(), SIGUSR2);
++    }
++}
++
++int setup_watchdog(struct tevent_context *ev, int interval)
++{
++    struct sigevent sev;
++    struct itimerspec its;
++    struct tevent_fd *tfd;
++    int signum = SIGRTMIN;
++    int ret;
++
++    ZERO_STRUCT(sev);
++    CatchSignal(signum, watchdog_handler);
++
++    sev.sigev_notify = SIGEV_SIGNAL;
++    sev.sigev_signo = signum;
++    sev.sigev_value.sival_ptr = &watchdog_ctx.timerid;
++    errno = 0;
++    ret = timer_create(CLOCK_MONOTONIC, &sev, &watchdog_ctx.timerid);
++    if (ret == -1) {
++        ret = errno;
++        DEBUG(SSSDBG_FATAL_FAILURE,
++              "Failed to create watchdog timer (%d) [%s]\n",
++              ret, strerror(ret));
++        return ret;
++    }
++
++    if (interval == 0) {
++        interval = WATCHDOG_DEF_INTERVAL;
++    }
++    watchdog_ctx.interval.tv_sec = interval;
++    watchdog_ctx.interval.tv_usec = 0;
++
++    watchdog_ctx.ev = ev;
++    watchdog_ctx.input_interval = interval;
++    watchdog_ctx.timestamp = time(NULL);
++
++    ret = pipe(watchdog_ctx.pipefd);
++    if (ret == -1) {
++        ret = errno;
++        DEBUG(SSSDBG_FATAL_FAILURE,
++              "pipe failed [%d] [%s].\n", ret, strerror(ret));
++        return ret;
++    }
++
++    sss_fd_nonblocking(watchdog_ctx.pipefd[0]);
++    sss_fd_nonblocking(watchdog_ctx.pipefd[1]);
++
++    tfd = tevent_add_fd(ev, (TALLOC_CTX *)ev, watchdog_ctx.pipefd[0],
++                        TEVENT_FD_READ, watchdog_fd_read_handler, NULL);
++    watchdog_ctx.tfd = tfd;
++
++    /* Start the timer */
++    /* we give 1 second head start to the watchdog event */
++    its.it_value.tv_sec = interval + 1;
++    its.it_value.tv_nsec = 0;
++    its.it_interval.tv_sec = interval;
++    its.it_interval.tv_nsec = 0;
++    errno = 0;
++    ret = timer_settime(watchdog_ctx.timerid, 0, &its, NULL);
++    if (ret == -1) {
++        ret = errno;
++        DEBUG(SSSDBG_FATAL_FAILURE,
++              "Failed to create watchdog timer (%d) [%s]\n",
++              ret, strerror(ret));
++        return ret;
++    }
++
++    /* Add the watchdog event and make it fire as fast as the timer */
++    watchdog_event_handler(ev, NULL, tevent_timeval_zero(), NULL);
++
++    return EOK;
++}
++
++void teardown_watchdog(void)
++{
++    int ret;
++
++    /* Disarm the timer */
++    errno = 0;
++    ret = timer_delete(watchdog_ctx.timerid);
++    if (ret == -1) {
++        ret = errno;
++        DEBUG(SSSDBG_FATAL_FAILURE,
++              "Failed to destroy watchdog timer (%d) [%s]\n",
++             ret, strerror(ret));
++    }
++
++    /* Free the tevent_fd */
++    talloc_zfree(watchdog_ctx.tfd);
++
++    /* Close the pipefds */
++    PIPE_FD_CLOSE(watchdog_ctx.pipefd[0]);
++    PIPE_FD_CLOSE(watchdog_ctx.pipefd[1]);
++
++    /* and kill the watchdog event */
++    talloc_free(watchdog_ctx.te);
++}
diff --git a/debian/patches/series b/debian/patches/series
index 8631edc..f940a0a 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -3,7 +3,7 @@ AD-add-new-option-ad_site.diff
 AD-support-for-AD-site-override.diff
 AD-SRV-prefer-site-local-DCs-in-LDAP-ping.diff
 fix-upstream-2519.diff
-restart_providers_on_timeshift.diff
-BUILD-Fix-linking-with-librt.diff
+restart_providers_on_timeshift.patch
+BUILD-Fix-linking-with-librt.patch
 pidfile-creation.diff
 sanitize_newline.diff



More information about the Pkg-sssd-devel mailing list