From 8bc4bb5f1273566c704d76ab584276bd5774b9d8 Mon Sep 17 00:00:00 2001
From: Christian Pointner <equinox@helsinki.at>
Date: Mon, 18 May 2015 04:53:32 +0200
Subject: fixed return code after signal or error


diff --git a/src/Makefile b/src/Makefile
index bb4a655..d9b8810 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -42,6 +42,7 @@ C_OBJS := log.o \
           writer.o \
           file_list.o \
           sysexec.o \
+          rhmain.o \
           rharchive.o
 
 C_SRCS := $(C_OBJS:%.o=%.c)
diff --git a/src/rharchive.c b/src/rharchive.c
index 96b6aa9..7014fdd 100644
--- a/src/rharchive.c
+++ b/src/rharchive.c
@@ -33,6 +33,9 @@
 #include <errno.h>
 #include <string.h>
 #include <sys/select.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <signal.h>
 
 #include <gst/gst.h>
 
@@ -42,16 +45,17 @@
 #include "log.h"
 #include "sig_handler.h"
 #include "daemon.h"
+#include "rhmain.h"
 #include "writer.h"
 
 static gboolean bus_call(GstBus *bus, GstMessage *msg, gpointer data)
 {
-  GMainLoop *loop = (GMainLoop *)data;
+  RHMainLoop *loop = (RHMainLoop *)data;
 
   switch (GST_MESSAGE_TYPE(msg)) {
   case GST_MESSAGE_EOS: {
     log_printf(NOTICE, "End of stream");
-    g_main_loop_quit(loop);
+    rhmain_loop_quit(loop, -3);
     break;
   }
   case GST_MESSAGE_INFO: {
@@ -73,7 +77,7 @@ static gboolean bus_call(GstBus *bus, GstMessage *msg, gpointer data)
     gst_message_parse_error(msg, &error, NULL);
     log_printf(ERROR, "%s", error->message);
     g_error_free(error);
-    g_main_loop_quit(loop);
+    rhmain_loop_quit(loop, -1);
     break;
   }
   default:
@@ -86,22 +90,26 @@ int main_loop(options_t* opt)
 {
   log_printf(INFO, "entering main loop");
 
-  GMainLoop *loop;
+  RHMainLoop loop;
   GstElement *pipeline, *source;
   GstBus *bus;
   writer_t writer;
 
-  loop = g_main_loop_new(NULL, FALSE);
+  if(!rhmain_loop_init(&loop)) {
+    log_printf(ERROR, "the loop object could not be created. Exiting.");
+    return -1;
+  }
+
   pipeline = gst_pipeline_new("rharchive");
-  if(!pipeline || !loop) {
-    log_printf(ERROR, "the pipeline/loop object could not be created. Exiting.");
+  if(!pipeline) {
+    log_printf(ERROR, "the pipeline object could not be created. Exiting.");
     return -1;
   }
 
-  int ret = writer_init(&writer, loop, opt->name_format_, opt->mode_, opt->nocache_, opt->output_dir_, opt->interval_, opt->offset_, opt->post_process_);
+  int ret = writer_init(&writer, &loop, opt->name_format_, opt->mode_, opt->nocache_, opt->output_dir_, opt->interval_, opt->offset_, opt->post_process_);
   if(ret) {
     gst_object_unref(GST_OBJECT(pipeline));
-    gst_object_unref(GST_OBJECT(loop));
+    rhmain_loop_destroy(&loop);
     return ret;
   }
 
@@ -112,14 +120,14 @@ int main_loop(options_t* opt)
     g_error_free(error);
     gst_object_unref(GST_OBJECT(writer.sink_));
     gst_object_unref(GST_OBJECT(pipeline));
-    gst_object_unref(GST_OBJECT(loop));
+    rhmain_loop_destroy(&loop);
     return -1;
   }
 
   gst_bin_add_many(GST_BIN(pipeline), source, writer.sink_, NULL);
   gst_element_link_many(source, writer.sink_, NULL);
   bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline));
-  gst_bus_add_watch(bus, bus_call, loop);
+  gst_bus_add_watch(bus, bus_call, &loop);
   gst_object_unref(bus);
 
   log_printf(INFO, "Set State: Paused");
@@ -127,10 +135,10 @@ int main_loop(options_t* opt)
   log_printf(INFO, "Set State: Playing");
   gst_element_set_state(pipeline, GST_STATE_PLAYING);
 
-  signal_start(loop);
+  signal_start(&loop);
   ret = writer_start(&writer);
   if(!ret) {
-    g_main_loop_run(loop);
+    ret = rhmain_loop_run(&loop);
     signal_stop();
   }
 
@@ -138,6 +146,7 @@ int main_loop(options_t* opt)
   gst_element_set_state (pipeline, GST_STATE_NULL);
   writer_stop(&writer);
   gst_object_unref(GST_OBJECT(pipeline));
+      //rhmain_loop_destroy(&loop);
 
   return ret;
 }
@@ -247,9 +256,18 @@ int main(int argc, char* argv[])
 
   options_clear(&opt);
 
-  log_printf(NOTICE, "rharchive shutdown");
-
   gst_deinit();
+
+  if(!ret)
+    log_printf(NOTICE, "normal shutdown");
+  else if(ret < 0)
+    log_printf(NOTICE, "shutdown after error");
+  else {
+    log_printf(NOTICE, "shutdown after signal");
+    log_close();
+    kill(getpid(), ret);
+  }
+
   log_close();
 
   return ret;
diff --git a/src/rhmain.c b/src/rhmain.c
new file mode 100644
index 0000000..cb8e330
--- /dev/null
+++ b/src/rhmain.c
@@ -0,0 +1,73 @@
+/*
+ *  rharchive
+ *
+ *  The Radio Helsinki Archive Daemon
+ *
+ *
+ *  Copyright (C) 2009-2015 Christian Pointner <equinox@helsinki.at>
+ *
+ *  This file is part of rharchive.
+ *
+ *  rharchive 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
+ *  any later version.
+ *
+ *  rharchive 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 rharchive. If not, see <http://www.gnu.org/licenses/>.
+ *
+ *  In addition, as a special exception, the copyright holders hereby
+ *  grant permission for non-GPL-compatible GStreamer plugins to be used
+ *  and distributed together with GStreamer and rharchive.
+ *  This permission goes above and beyond the permissions granted by the
+ *  GPL license rharchive is covered by.
+ */
+
+#include "rhmain.h"
+
+#include <glib.h>
+#include <gst/gst.h>
+
+gboolean rhmain_loop_init(RHMainLoop* loop)
+{
+  if(!loop)
+    return FALSE;
+
+  loop->exit_code = 0;
+  loop->gloop = g_main_loop_new(NULL, FALSE);
+  if(!loop->gloop)
+    return FALSE;
+
+  return TRUE;
+}
+
+void rhmain_loop_destroy(RHMainLoop* loop)
+{
+  if(!loop)
+    return;
+
+  gst_object_unref(GST_OBJECT(loop->gloop));
+}
+
+gint rhmain_loop_run(RHMainLoop* loop)
+{
+  if(!loop)
+    return -2;
+
+  g_main_loop_run(loop->gloop);
+  return g_atomic_int_get(&(loop->exit_code));
+}
+
+void rhmain_loop_quit(RHMainLoop* loop, gint exit_code)
+{
+  if(!loop)
+    return;
+
+  g_main_loop_quit(loop->gloop);
+  g_atomic_int_set(&(loop->exit_code), exit_code);
+}
diff --git a/src/rhmain.h b/src/rhmain.h
new file mode 100644
index 0000000..bcbdd8e
--- /dev/null
+++ b/src/rhmain.h
@@ -0,0 +1,46 @@
+/*
+ *  rharchive
+ *
+ *  The Radio Helsinki Archive Daemon
+ *
+ *
+ *  Copyright (C) 2009-2015 Christian Pointner <equinox@helsinki.at>
+ *
+ *  This file is part of rharchive.
+ *
+ *  rharchive 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
+ *  any later version.
+ *
+ *  rharchive 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 rharchive. If not, see <http://www.gnu.org/licenses/>.
+ *
+ *  In addition, as a special exception, the copyright holders hereby
+ *  grant permission for non-GPL-compatible GStreamer plugins to be used
+ *  and distributed together with GStreamer and rharchive.
+ *  This permission goes above and beyond the permissions granted by the
+ *  GPL license rharchive is covered by.
+ */
+
+#ifndef RHARCHIVE_rhmain_h_INCLUDED
+#define RHARCHIVE_rhmain_h_INCLUDED
+
+#include <glib.h>
+
+typedef struct {
+  GMainLoop *gloop;
+  volatile gint exit_code;
+} RHMainLoop;
+
+gboolean rhmain_loop_init(RHMainLoop* loop);
+void rhmain_loop_destroy(RHMainLoop* loop);
+gint rhmain_loop_run(RHMainLoop* loop);
+void rhmain_loop_quit(RHMainLoop* loop, gint exit_code);
+
+#endif
diff --git a/src/sig_handler.c b/src/sig_handler.c
index 75ef4f4..aa20a98 100644
--- a/src/sig_handler.c
+++ b/src/sig_handler.c
@@ -37,6 +37,8 @@
 #include <glib.h>
 #include <errno.h>
 
+#include "rhmain.h"
+
 static GThread *signal_thread;
 
 void signal_init()
@@ -56,7 +58,7 @@ void signal_init()
 
 static gpointer signal_thread_func(gpointer data)
 {
-  GMainLoop *loop = (GMainLoop *)data;
+  RHMainLoop *loop = (RHMainLoop *)data;
 
   struct timespec timeout;
   sigset_t signal_set;
@@ -83,7 +85,7 @@ static gpointer signal_thread_func(gpointer data)
         case SIGINT:
         case SIGQUIT: {
           log_printf(NOTICE, "signal %d received, exiting", sig_num);
-          g_main_loop_quit(loop);
+          rhmain_loop_quit(loop, sig_num);
           break;
         }
         default: {
@@ -97,7 +99,7 @@ static gpointer signal_thread_func(gpointer data)
   return NULL;
 }
 
-int signal_start(GMainLoop *loop)
+int signal_start(RHMainLoop *loop)
 {
   g_assert(!signal_thread);
 
@@ -110,5 +112,15 @@ int signal_start(GMainLoop *loop)
 
 void signal_stop()
 {
-      // nothing yet..
+  sigset_t signal_set;
+
+  sigemptyset(&signal_set);
+  sigaddset(&signal_set, SIGINT);
+  sigaddset(&signal_set, SIGQUIT);
+  sigaddset(&signal_set, SIGHUP);
+  sigaddset(&signal_set, SIGTERM);
+  sigaddset(&signal_set, SIGUSR1);
+  sigaddset(&signal_set, SIGUSR2);
+
+  pthread_sigmask(SIG_UNBLOCK, &signal_set, NULL);
 }
diff --git a/src/sig_handler.h b/src/sig_handler.h
index 0d138d2..4847aec 100644
--- a/src/sig_handler.h
+++ b/src/sig_handler.h
@@ -31,10 +31,10 @@
 #ifndef RHARCHIVE_sig_handler_h_INCLUDED
 #define RHARCHIVE_sig_handler_h_INCLUDED
 
-#include <glib.h>
+#include "rhmain.h"
 
 void signal_init();
-int signal_start(GMainLoop *loop);
+int signal_start(RHMainLoop *loop);
 void signal_stop();
 
 #endif
diff --git a/src/writer.c b/src/writer.c
index e434320..ab41eb4 100644
--- a/src/writer.c
+++ b/src/writer.c
@@ -41,6 +41,7 @@
 #include "datatypes.h"
 #include "log.h"
 #include "file_list.h"
+#include "rhmain.h"
 
 static int init_time_boundaries(writer_t* writer)
 {
@@ -98,7 +99,7 @@ static void fdremoved_cb(GstElement* sink, gint fd, gpointer data)
     file_list_remove(&(writer->files_), fd);
 }
 
-int writer_init(writer_t* writer, GMainLoop *loop, const char* name_format, mode_t mode, int nocache, const char* output_dir, int interval, int offset, char* post_process)
+int writer_init(writer_t* writer, RHMainLoop *loop, const char* name_format, mode_t mode, int nocache, const char* output_dir, int interval, int offset, char* post_process)
 {
   if(!writer)
     return -1;
@@ -198,7 +199,7 @@ static gpointer writer_thread_func(gpointer data)
   }
 
   log_printf(NOTICE, "writer thread stopped");
-  g_main_loop_quit(writer->loop_);
+  rhmain_loop_quit(writer->loop_, -1);
   return NULL;
 }
 
diff --git a/src/writer.h b/src/writer.h
index 79f3a3c..073f805 100644
--- a/src/writer.h
+++ b/src/writer.h
@@ -36,10 +36,11 @@
 #include <time.h>
 #include <sys/types.h>
 
+#include "rhmain.h"
 #include "file_list.h"
 
 struct writer_struct {
-  GMainLoop *loop_;
+  RHMainLoop *loop_;
   GstElement* sink_;
   GstClock* clock_;
   GstClockID clock_id_;
@@ -58,7 +59,7 @@ struct writer_struct {
 };
 typedef struct writer_struct writer_t;
 
-int writer_init(writer_t* writer, GMainLoop *loop, const char* name_format, mode_t mode, int nocache, const char* output_dir, int interval, int offset, char* post_process);
+int writer_init(writer_t* writer, RHMainLoop *loop, const char* name_format, mode_t mode, int nocache, const char* output_dir, int interval, int offset, char* post_process);
 int writer_start(writer_t* writer);
 void writer_stop(writer_t* writer);
 
-- 
cgit v0.10.2