2626#include < pthread.h>
2727#endif
2828
29+ #ifdef __linux__
30+ #include < poll.h>
31+ #include < sys/signalfd.h>
32+ #include < sys/eventfd.h>
33+ #endif
34+
2935#include " types.h"
3036#include < string.h>
3137#include < errno.h>
@@ -142,6 +148,35 @@ struct jackctl_parameter
142148 jack_driver_param_constraint_desc_t * constraint_ptr;
143149};
144150
151+ #ifdef __linux__
152+ /* * Jack file descriptors */
153+ typedef enum
154+ {
155+ JackSignalFD, /* *< @brief File descriptor to accept the signals */
156+ JackEventFD, /* *< @brief File descriptor to accept the events from threads */
157+ JackFDCount /* *< @brief FD count, ensure this is the last element */
158+ } jackctl_fd;
159+
160+ static int eventFD;
161+ #endif
162+
163+ static
164+ void
165+ on_failure ()
166+ {
167+ #ifdef __linux__
168+ int ret = 0 ;
169+ const uint64_t ev = 1 ;
170+
171+ ret = write (eventFD, &ev, sizeof (ev));
172+ if (ret < 0 ) {
173+ fprintf (stderr, " JackServerGlobals::on_failure : write() failed with errno %d\n " , -errno);
174+ }
175+ #else
176+ fprintf (stderr, " JackServerGlobals::on_failure callback called from thread\n " );
177+ #endif
178+ }
179+
145180const char * jack_get_self_connect_mode_description (char mode)
146181{
147182 struct jack_constraint_enum_char_descriptor * descr_ptr;
@@ -679,16 +714,70 @@ jackctl_setup_signals(
679714SERVER_EXPORT void
680715jackctl_wait_signals (jackctl_sigmask_t * sigmask)
681716{
682- int sig;
717+ int sig = 0 ;
683718 bool waiting = true ;
719+ #ifdef __linux__
720+ int err;
721+ struct pollfd pfd[JackFDCount];
722+ struct signalfd_siginfo si;
723+ memset (pfd, 0 , sizeof (pfd));
724+
725+ /* Block the signals in order for signalfd to receive them */
726+ sigprocmask (SIG_BLOCK, &sigmask->signals , NULL );
727+
728+ pfd[JackSignalFD].fd = signalfd (-1 , &sigmask->signals , 0 );
729+ if (pfd[JackSignalFD].fd == -1 ) {
730+ fprintf (stderr, " signalfd() failed with errno %d\n " , -errno);
731+ return ;
732+ }
733+ pfd[JackSignalFD].events = POLLIN;
734+
735+ pfd[JackEventFD].fd = eventfd (0 , EFD_NONBLOCK);
736+ if (pfd[JackEventFD].fd == -1 ) {
737+ goto fail;
738+ }
739+ eventFD = pfd[JackEventFD].fd ;
740+ pfd[JackEventFD].events = POLLIN;
741+
742+ #endif
684743
685744 while (waiting) {
686745 #if defined(sun) && !defined(__sun__) // SUN compiler only, to check
687746 sigwait (&sigmask->signals );
747+ fprintf (stderr, " Jack main caught signal\n " );
748+ #elif defined(__linux__)
749+ err = poll (pfd, JackFDCount, -1 );
750+ if (err < 0 ) {
751+ if (errno == EINTR) {
752+ continue ;
753+ } else {
754+ fprintf (stderr, " Jack : poll() failed with errno %d\n " , -errno);
755+ break ;
756+ }
757+ } else {
758+ if ((pfd[JackSignalFD].revents & (POLLERR | POLLHUP | POLLNVAL)) ||
759+ pfd[JackEventFD].revents & (POLLERR | POLLHUP | POLLNVAL)) {
760+ fprintf (stderr, " Jack : poll() exited with errno %d\n " , -errno);
761+ break ;
762+ } else if ((pfd[JackSignalFD].revents & POLLIN) != 0 ) {
763+ err = read (pfd[JackSignalFD].fd , &si, sizeof (si));
764+ if (err < 0 ) {
765+ fprintf (stderr, " Jack : read() on signalfd failed with errno %d\n " , -errno);
766+ break ;
767+ }
768+ sig = si.ssi_signo ;
769+ fprintf (stderr, " Jack main caught signal %d\n " , sig);
770+ } else if ((pfd[JackEventFD].revents & POLLIN) != 0 ) {
771+ sig = 0 ; /* Received an event from one of the Jack thread */
772+ fprintf (stderr, " Jack main received event from child thread, Exiting\n " );
773+ } else {
774+ continue ;
775+ }
776+ }
688777 #else
689778 sigwait (&sigmask->signals , &sig);
690- #endif
691779 fprintf (stderr, " Jack main caught signal %d\n " , sig);
780+ #endif
692781
693782 switch (sig) {
694783 case SIGUSR1:
@@ -712,6 +801,16 @@ jackctl_wait_signals(jackctl_sigmask_t * sigmask)
712801 // bugs that cause segfaults etc. during shutdown.
713802 sigprocmask (SIG_UNBLOCK, &sigmask->signals , 0 );
714803 }
804+
805+ #ifdef __linux__
806+ fail:
807+ for (int i = 0 ; i < JackFDCount; i++) {
808+ if (pfd[i].fd != 0 ) {
809+ close (pfd[i].fd );
810+ }
811+ }
812+ #endif
813+
715814}
716815#endif
717816
@@ -931,6 +1030,7 @@ SERVER_EXPORT jackctl_server_t * jackctl_server_create2(
9311030 JackServerGlobals::on_device_acquire = on_device_acquire;
9321031 JackServerGlobals::on_device_release = on_device_release;
9331032 JackServerGlobals::on_device_reservation_loop = on_device_reservation_loop;
1033+ JackServerGlobals::on_failure = on_failure;
9341034
9351035 if (!jackctl_drivers_load (server_ptr))
9361036 {
0 commit comments