File jack2-PR_462.patch of Package jack

From fc9046998b6cdf048de57f5e55e182de095bb167 Mon Sep 17 00:00:00 2001
From: Laxmi Devi <Laxmi.Devi@in.bosch.com>
Date: Wed, 15 May 2019 11:57:52 +0530
Subject: [PATCH 1/2] JackControlAPI: Replacing sigwait with signalfd and poll

This would be required so that the polling concept can be used to wait
on signals as well as wait for events from the other threads.

Signed-off-by: Laxmi Devi <Laxmi.Devi@in.bosch.com>
---
 common/JackControlAPI.cpp | 55 +++++++++++++++++++++++++++++++++++++--
 1 file changed, 53 insertions(+), 2 deletions(-)

diff --git a/common/JackControlAPI.cpp b/common/JackControlAPI.cpp
index 4d597e7d..632620e3 100644
--- a/common/JackControlAPI.cpp
+++ b/common/JackControlAPI.cpp
@@ -26,6 +26,11 @@
 #include <pthread.h>
 #endif
 
+#ifdef __linux__
+#include <poll.h>
+#include <sys/signalfd.h>
+#endif
+
 #include "types.h"
 #include <string.h>
 #include <errno.h>
@@ -677,16 +682,56 @@ jackctl_setup_signals(
 SERVER_EXPORT void
 jackctl_wait_signals(jackctl_sigmask_t * sigmask)
 {
-    int sig;
+    int sig = 0;
     bool waiting = true;
+#ifdef __linux__
+    int err;
+    struct pollfd pfd;
+    struct signalfd_siginfo si;
+
+    /* Block the signals in order for signalfd to receive them */
+    sigprocmask(SIG_BLOCK, &sigmask->signals, NULL);
+
+    pfd.fd = signalfd(-1, &sigmask->signals, 0);
+    if(pfd.fd == -1) {
+        fprintf(stderr, "Jack : signalfd() failed with errno %d\n", -errno);
+        return;
+    }
+    pfd.events = POLLIN;
+#endif
 
     while (waiting) {
     #if defined(sun) && !defined(__sun__) // SUN compiler only, to check
         sigwait(&sigmask->signals);
+        fprintf(stderr, "Jack main caught signal\n");
+    #elif defined(__linux__)
+        err = poll(&pfd, 1, -1);
+        if (err < 0) {
+            if (errno == EINTR) {
+                continue;
+            } else {
+                fprintf(stderr, "Jack : poll() failed with errno %d\n", -errno);
+                break;
+            }
+        } else {
+            if (pfd.revents & (POLLERR | POLLHUP | POLLNVAL)) {
+                fprintf(stderr, "Jack : poll() exited with errno %d\n", -errno);
+                break;
+            } else if ((pfd.revents & POLLIN) == 0) {
+                continue;
+            }
+            err = read (pfd.fd, &si, sizeof(si));
+            if (err < 0) {
+                fprintf(stderr, "Jack : read() on signalfd failed with errno %d\n", -errno);
+                goto fail;
+            }
+            sig = si.ssi_signo;
+            fprintf(stderr, "Jack main caught signal %d\n", sig);
+        }
     #else
         sigwait(&sigmask->signals, &sig);
-    #endif
         fprintf(stderr, "Jack main caught signal %d\n", sig);
+    #endif
 
         switch (sig) {
             case SIGUSR1:
@@ -710,6 +755,12 @@ jackctl_wait_signals(jackctl_sigmask_t * sigmask)
         // bugs that cause segfaults etc. during shutdown.
         sigprocmask(SIG_UNBLOCK, &sigmask->signals, 0);
     }
+
+#ifdef __linux__
+fail:
+    close(pfd.fd);
+#endif
+
 }
 #endif
 

From 5435c546056ffe42ab92da46b8b8eecca240233b Mon Sep 17 00:00:00 2001
From: Laxmi Devi <Laxmi.Devi@in.bosch.com>
Date: Wed, 22 May 2019 14:17:08 +0530
Subject: [PATCH 2/2] JackControlAPI: Jack threads to notify failure to jackd
 by posting an event

On failure, currently the jack thread exits without notifying the jackd.
So jackd is just waiting for the signals, unaware of the failure.
With this implementation, on error threads can post an event to jackd
notifying it to to exit.

Signed-off-by: Laxmi Devi <Laxmi.Devi@in.bosch.com>
---
 common/JackAudioDriver.cpp   |  7 +++-
 common/JackControlAPI.cpp    | 81 +++++++++++++++++++++++++++++-------
 common/JackServerGlobals.cpp |  1 +
 common/JackServerGlobals.h   |  1 +
 4 files changed, 73 insertions(+), 17 deletions(-)

diff --git a/common/JackAudioDriver.cpp b/common/JackAudioDriver.cpp
index ac686e3a..ef7c683d 100644
--- a/common/JackAudioDriver.cpp
+++ b/common/JackAudioDriver.cpp
@@ -28,6 +28,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 #include "JackLockedEngine.h"
 #include "JackException.h"
 #include <assert.h>
+#include "JackServerGlobals.h"
 
 using namespace std;
 
@@ -199,7 +200,11 @@ int JackAudioDriver::Write()
 
 int JackAudioDriver::Process()
 {
-    return (fEngineControl->fSyncMode) ? ProcessSync() : ProcessAsync();
+    int err = (fEngineControl->fSyncMode) ? ProcessSync() : ProcessAsync();
+    if(err && JackServerGlobals::on_failure != NULL) {
+        JackServerGlobals::on_failure();
+    }
+    return err;
 }
 
 /*
diff --git a/common/JackControlAPI.cpp b/common/JackControlAPI.cpp
index 632620e3..26dafabb 100644
--- a/common/JackControlAPI.cpp
+++ b/common/JackControlAPI.cpp
@@ -29,6 +29,7 @@
 #ifdef __linux__
 #include <poll.h>
 #include <sys/signalfd.h>
+#include <sys/eventfd.h>
 #endif
 
 #include "types.h"
@@ -147,6 +148,35 @@ struct jackctl_parameter
     jack_driver_param_constraint_desc_t * constraint_ptr;
 };
 
+#ifdef __linux__
+/** Jack file descriptors */
+typedef enum
+{
+    JackSignalFD,			/**< @brief File descriptor to accept the signals */
+    JackEventFD,			/**< @brief File descriptor to accept the events from threads */
+    JackFDCount				/**< @brief FD count, ensure this is the last element */
+} jackctl_fd;
+
+static int eventFD;
+#endif
+
+static
+void
+on_failure()
+{
+#ifdef __linux__
+    int ret = 0;
+    const uint64_t ev = 1;
+
+    ret = write(eventFD, &ev, sizeof(ev));
+    if (ret < 0) {
+        fprintf(stderr, "JackServerGlobals::on_failure : write() failed with errno %d\n", -errno);
+    }
+#else
+    fprintf(stderr, "JackServerGlobals::on_failure callback called from thread\n");
+#endif
+}
+
 const char * jack_get_self_connect_mode_description(char mode)
 {
     struct jack_constraint_enum_char_descriptor * descr_ptr;
@@ -686,18 +716,27 @@ jackctl_wait_signals(jackctl_sigmask_t * sigmask)
     bool waiting = true;
 #ifdef __linux__
     int err;
-    struct pollfd pfd;
+    struct pollfd pfd[JackFDCount];
     struct signalfd_siginfo si;
+    memset(pfd, 0, sizeof(pfd));
 
     /* Block the signals in order for signalfd to receive them */
     sigprocmask(SIG_BLOCK, &sigmask->signals, NULL);
 
-    pfd.fd = signalfd(-1, &sigmask->signals, 0);
-    if(pfd.fd == -1) {
-        fprintf(stderr, "Jack : signalfd() failed with errno %d\n", -errno);
+    pfd[JackSignalFD].fd = signalfd(-1, &sigmask->signals, 0);
+    if(pfd[JackSignalFD].fd == -1) {
+        fprintf(stderr, "signalfd() failed with errno %d\n", -errno);
         return;
     }
-    pfd.events = POLLIN;
+    pfd[JackSignalFD].events = POLLIN;
+
+    pfd[JackEventFD].fd = eventfd(0, EFD_NONBLOCK);
+    if(pfd[JackEventFD].fd == -1) {
+        goto fail;
+    }
+    eventFD = pfd[JackEventFD].fd;
+    pfd[JackEventFD].events = POLLIN;
+
 #endif
 
     while (waiting) {
@@ -705,7 +744,7 @@ jackctl_wait_signals(jackctl_sigmask_t * sigmask)
         sigwait(&sigmask->signals);
         fprintf(stderr, "Jack main caught signal\n");
     #elif defined(__linux__)
-        err = poll(&pfd, 1, -1);
+        err = poll(pfd, JackFDCount, -1);
         if (err < 0) {
             if (errno == EINTR) {
                 continue;
@@ -714,19 +753,24 @@ jackctl_wait_signals(jackctl_sigmask_t * sigmask)
                 break;
             }
         } else {
-            if (pfd.revents & (POLLERR | POLLHUP | POLLNVAL)) {
+            if ((pfd[JackSignalFD].revents & (POLLERR | POLLHUP | POLLNVAL)) ||
+                 pfd[JackEventFD].revents & (POLLERR | POLLHUP | POLLNVAL)) {
                 fprintf(stderr, "Jack : poll() exited with errno %d\n", -errno);
                 break;
-            } else if ((pfd.revents & POLLIN) == 0) {
+            } else if ((pfd[JackSignalFD].revents & POLLIN) != 0) {
+                err = read (pfd[JackSignalFD].fd, &si, sizeof(si));
+                if (err < 0) {
+                    fprintf(stderr, "Jack : read() on signalfd failed with errno %d\n", -errno);
+                    break;
+                }
+                sig = si.ssi_signo;
+                fprintf(stderr, "Jack main caught signal %d\n", sig);
+            } else if ((pfd[JackEventFD].revents & POLLIN) != 0) {
+                sig = 0; /* Received an event from one of the Jack thread */
+                fprintf(stderr, "Jack main received event from child thread, Exiting\n");
+            } else {
                 continue;
             }
-            err = read (pfd.fd, &si, sizeof(si));
-            if (err < 0) {
-                fprintf(stderr, "Jack : read() on signalfd failed with errno %d\n", -errno);
-                goto fail;
-            }
-            sig = si.ssi_signo;
-            fprintf(stderr, "Jack main caught signal %d\n", sig);
         }
     #else
         sigwait(&sigmask->signals, &sig);
@@ -758,7 +802,11 @@ jackctl_wait_signals(jackctl_sigmask_t * sigmask)
 
 #ifdef __linux__
 fail:
-    close(pfd.fd);
+    for(int i = 0; i < JackFDCount; i++) {
+        if(pfd[i].fd != 0) {
+            close(pfd[i].fd);
+        }
+    }
 #endif
 
 }
@@ -971,6 +1019,7 @@ SERVER_EXPORT jackctl_server_t * jackctl_server_create(
 
     JackServerGlobals::on_device_acquire = on_device_acquire;
     JackServerGlobals::on_device_release = on_device_release;
+    JackServerGlobals::on_failure = on_failure;
 
     if (!jackctl_drivers_load(server_ptr))
     {
diff --git a/common/JackServerGlobals.cpp b/common/JackServerGlobals.cpp
index 16688411..592fb138 100644
--- a/common/JackServerGlobals.cpp
+++ b/common/JackServerGlobals.cpp
@@ -36,6 +36,7 @@ std::map<std::string, int> JackServerGlobals::fInternalsList;
 
 bool (* JackServerGlobals::on_device_acquire)(const char * device_name) = NULL;
 void (* JackServerGlobals::on_device_release)(const char * device_name) = NULL;
+void (* JackServerGlobals::on_failure)() = NULL;
 
 int JackServerGlobals::Start(const char* server_name,
                              jack_driver_desc_t* driver_desc,
diff --git a/common/JackServerGlobals.h b/common/JackServerGlobals.h
index beb1880f..ac5f46ed 100644
--- a/common/JackServerGlobals.h
+++ b/common/JackServerGlobals.h
@@ -44,6 +44,7 @@ struct SERVER_EXPORT JackServerGlobals
 
     static bool (* on_device_acquire)(const char* device_name);
     static void (* on_device_release)(const char* device_name);
+    static void (* on_failure)(); /* Optional callback to be called from any thread on failure */
 
     JackServerGlobals();
     ~JackServerGlobals();
openSUSE Build Service is sponsored by