mirror of
https://github.com/owntone/owntone-server.git
synced 2025-03-31 17:53:49 -04:00
Move signal handling to parent thread, add -V and -k options, closing #219, and fixing problems with daemontools
This commit is contained in:
parent
5f922b44d8
commit
d2e5b45bd9
19
src/main.c
19
src/main.c
@ -222,6 +222,7 @@ int main(int argc, char *argv[]) {
|
|||||||
int old_song_count, song_count;
|
int old_song_count, song_count;
|
||||||
int force_non_root=0;
|
int force_non_root=0;
|
||||||
int skip_initial=1;
|
int skip_initial=1;
|
||||||
|
int kill_server=0;
|
||||||
int convert_conf=0;
|
int convert_conf=0;
|
||||||
char *db_type,*db_parms,*web_root,*runas, *tmp;
|
char *db_type,*db_parms,*web_root,*runas, *tmp;
|
||||||
char **mp3_dir_array;
|
char **mp3_dir_array;
|
||||||
@ -248,7 +249,7 @@ int main(int argc, char *argv[]) {
|
|||||||
err_setlevel(2);
|
err_setlevel(2);
|
||||||
|
|
||||||
config.foreground=0;
|
config.foreground=0;
|
||||||
while((option=getopt(argc,argv,"D:d:c:P:mfrysiuvab:")) != -1) {
|
while((option=getopt(argc,argv,"D:d:c:P:mfrysiuvab:Vk")) != -1) {
|
||||||
switch(option) {
|
switch(option) {
|
||||||
case 'a':
|
case 'a':
|
||||||
appdir = 1;
|
appdir = 1;
|
||||||
@ -315,6 +316,14 @@ int main(int argc, char *argv[]) {
|
|||||||
convert_conf=1;
|
convert_conf=1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'k':
|
||||||
|
kill_server=1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'V':
|
||||||
|
fprintf(stderr,"Firefly Media Server: Version %s\n",VERSION);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
usage(argv[0]);
|
usage(argv[0]);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
@ -329,6 +338,12 @@ int main(int argc, char *argv[]) {
|
|||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if(kill_server) {
|
||||||
|
os_signal_server(S_STOP);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
/* read the configfile, if specified, otherwise
|
/* read the configfile, if specified, otherwise
|
||||||
* try defaults */
|
* try defaults */
|
||||||
config.stats.start_time=start_time=(int)time(NULL);
|
config.stats.start_time=start_time=(int)time(NULL);
|
||||||
@ -562,7 +577,7 @@ int main(int argc, char *argv[]) {
|
|||||||
time(NULL)-start_time);
|
time(NULL)-start_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
sleep(MAIN_SLEEP_INTERVAL);
|
os_wait(MAIN_SLEEP_INTERVAL);
|
||||||
rescan_counter += MAIN_SLEEP_INTERVAL;
|
rescan_counter += MAIN_SLEEP_INTERVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
209
src/os-unix.c
209
src/os-unix.c
@ -55,7 +55,7 @@
|
|||||||
#include "conf.h"
|
#include "conf.h"
|
||||||
#include "err.h"
|
#include "err.h"
|
||||||
#include "daapd.h"
|
#include "daapd.h"
|
||||||
#include "os-unix.h"
|
#include "os.h"
|
||||||
|
|
||||||
/** You say po-tay-to, I say po-tat-o */
|
/** You say po-tay-to, I say po-tat-o */
|
||||||
#ifndef SIGCLD
|
#ifndef SIGCLD
|
||||||
@ -69,12 +69,9 @@
|
|||||||
|
|
||||||
/* Forwards */
|
/* Forwards */
|
||||||
static int _os_daemon_start(void);
|
static int _os_daemon_start(void);
|
||||||
static void *_os_signal_handler(void *arg);
|
static int _os_start_signal_handler(void);
|
||||||
static int _os_start_signal_handler(pthread_t *handler_tid);
|
|
||||||
static volatile int _os_signal_pid;
|
|
||||||
|
|
||||||
/* Globals */
|
/* Globals */
|
||||||
pthread_t _os_signal_tid;
|
|
||||||
char *_os_pidfile = PIDFILE;
|
char *_os_pidfile = PIDFILE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -98,7 +95,8 @@ int os_init(int foreground, char *runas) {
|
|||||||
DPRINTF(E_LOG,L_MAIN,"fdopen: %s\n",strerror(errno));
|
DPRINTF(E_LOG,L_MAIN,"fdopen: %s\n",strerror(errno));
|
||||||
}
|
}
|
||||||
/* just to be on the safe side... */
|
/* just to be on the safe side... */
|
||||||
_os_signal_pid=0;
|
fprintf(pid_fp,"%d\n",getpid());
|
||||||
|
fclose(pid_fp);
|
||||||
_os_daemon_start();
|
_os_daemon_start();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,20 +107,10 @@ int os_init(int foreground, char *runas) {
|
|||||||
|
|
||||||
/* block signals and set up the signal handling thread */
|
/* block signals and set up the signal handling thread */
|
||||||
DPRINTF(E_LOG,L_MAIN,"Starting signal handler\n");
|
DPRINTF(E_LOG,L_MAIN,"Starting signal handler\n");
|
||||||
if(_os_start_signal_handler(&_os_signal_tid)) {
|
if(_os_start_signal_handler()) {
|
||||||
DPRINTF(E_FATAL,L_MAIN,"Error starting signal handler %s\n",strerror(errno));
|
DPRINTF(E_FATAL,L_MAIN,"Error starting signal handler %s\n",strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(pid_fp) {
|
|
||||||
/* wait to for config.pid to be set by the signal handler */
|
|
||||||
while(!_os_signal_pid) {
|
|
||||||
sleep(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(pid_fp,"%d\n",_os_signal_pid);
|
|
||||||
fclose(pid_fp);
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,10 +118,6 @@ int os_init(int foreground, char *runas) {
|
|||||||
* do any deinitialization necessary for the platform
|
* do any deinitialization necessary for the platform
|
||||||
*/
|
*/
|
||||||
void os_deinit(void) {
|
void os_deinit(void) {
|
||||||
DPRINTF(E_LOG,L_MAIN,"Stopping signal handler\n");
|
|
||||||
if(!pthread_kill(_os_signal_tid,SIGTERM)) {
|
|
||||||
pthread_join(_os_signal_tid,NULL);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -230,6 +214,51 @@ extern int os_chown(char *path, char *user) {
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* find the old service pid and send it a SIGTERM
|
||||||
|
*/
|
||||||
|
int os_signal_server(int what) {
|
||||||
|
FILE *pid_fp;
|
||||||
|
int pid;
|
||||||
|
int result = TRUE;
|
||||||
|
int signal;
|
||||||
|
|
||||||
|
if(NULL == (pid_fp = fopen(_os_pidfile, "r"))) {
|
||||||
|
DPRINTF(E_LOG,L_MAIN,"fdopen: %s\n",strerror(errno));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(fscanf(pid_fp,"%d\n",&pid)) {
|
||||||
|
kill(pid,SIGTERM);
|
||||||
|
} else {
|
||||||
|
DPRINTF(E_LOG,L_MAIN,"os_service_kill: can't get pid from pidfile\n");
|
||||||
|
result = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(pid_fp);
|
||||||
|
|
||||||
|
switch(what) {
|
||||||
|
case S_SCAN:
|
||||||
|
signal=SIGUSR1;
|
||||||
|
break;
|
||||||
|
case S_FULL:
|
||||||
|
signal=SIGUSR2;
|
||||||
|
break;
|
||||||
|
case S_STOP:
|
||||||
|
signal=SIGSTOP;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if(kill(pid,signal)) {
|
||||||
|
perror("kill");
|
||||||
|
result = FALSE;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fork and exit. Stolen pretty much straight from Stevens.
|
* Fork and exit. Stolen pretty much straight from Stevens.
|
||||||
*
|
*
|
||||||
@ -325,6 +354,69 @@ int os_drop_privs(char *user) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* wait for specified time, while setting signal flags
|
||||||
|
* (if necessary)
|
||||||
|
*/
|
||||||
|
void os_wait(int seconds) {
|
||||||
|
sigset_t intmask;
|
||||||
|
int sig;
|
||||||
|
int status;
|
||||||
|
int done=0;
|
||||||
|
|
||||||
|
sleep(seconds);
|
||||||
|
|
||||||
|
while(!done) {
|
||||||
|
if(!sigpending(&intmask)) {
|
||||||
|
if(sigismember(&intmask, SIGCLD) ||
|
||||||
|
sigismember(&intmask, SIGINT) ||
|
||||||
|
sigismember(&intmask, SIGHUP) ||
|
||||||
|
sigismember(&intmask, SIGTERM)) {
|
||||||
|
/* do a sigwait for it */
|
||||||
|
if((sigemptyset(&intmask) == -1) ||
|
||||||
|
(sigaddset(&intmask, SIGCLD) == -1) ||
|
||||||
|
(sigaddset(&intmask, SIGINT) == -1) ||
|
||||||
|
(sigaddset(&intmask, SIGHUP) == -1) ||
|
||||||
|
(sigaddset(&intmask, SIGTERM) == -1) ||
|
||||||
|
(sigwait(&intmask, &sig) == -1)) {
|
||||||
|
DPRINTF(E_FATAL,L_MAIN,"Error waiting for signals.");
|
||||||
|
} else {
|
||||||
|
/* process the signal */
|
||||||
|
switch(sig) {
|
||||||
|
case SIGCLD:
|
||||||
|
DPRINTF(E_LOG,L_MAIN,"Got CLD signal. Reaping\n");
|
||||||
|
while (wait3(&status, WNOHANG, NULL) > 0) {};
|
||||||
|
break;
|
||||||
|
case SIGTERM:
|
||||||
|
case SIGINT:
|
||||||
|
DPRINTF(E_LOG,L_MAIN,"Got shutdown signal.\n");
|
||||||
|
config.stop=1;
|
||||||
|
return;
|
||||||
|
break;
|
||||||
|
case SIGHUP:
|
||||||
|
DPRINTF(E_LOG,L_MAIN,"Got HUP signal.\n");
|
||||||
|
/* if we can't reload, it keeps the old config file,
|
||||||
|
* so no real damage */
|
||||||
|
conf_reload();
|
||||||
|
err_reopen();
|
||||||
|
|
||||||
|
config.reload=1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
DPRINTF(E_LOG,L_MAIN,"What am I doing here?\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
done=1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
DPRINTF(E_FATAL,L_MAIN,"Error in sigpending\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wait for signals and flag the main process. This is
|
* Wait for signals and flag the main process. This is
|
||||||
* a thread handler for the signal processing thread. It
|
* a thread handler for the signal processing thread. It
|
||||||
@ -335,58 +427,6 @@ int os_drop_privs(char *user) {
|
|||||||
* the stop flag (from an INT signal), and the reload flag (from HUP).
|
* the stop flag (from an INT signal), and the reload flag (from HUP).
|
||||||
* \param arg NULL, but required of a thread procedure
|
* \param arg NULL, but required of a thread procedure
|
||||||
*/
|
*/
|
||||||
void *_os_signal_handler(void *arg) {
|
|
||||||
sigset_t intmask;
|
|
||||||
int sig;
|
|
||||||
int status;
|
|
||||||
|
|
||||||
config.stop=0;
|
|
||||||
config.reload=0;
|
|
||||||
_os_signal_pid=getpid();
|
|
||||||
|
|
||||||
DPRINTF(E_WARN,L_MAIN,"Signal handler started\n");
|
|
||||||
|
|
||||||
while(!config.stop) {
|
|
||||||
if((sigemptyset(&intmask) == -1) ||
|
|
||||||
(sigaddset(&intmask, SIGCLD) == -1) ||
|
|
||||||
(sigaddset(&intmask, SIGINT) == -1) ||
|
|
||||||
(sigaddset(&intmask, SIGHUP) == -1) ||
|
|
||||||
(sigaddset(&intmask, SIGTERM) == -1) ||
|
|
||||||
(sigwait(&intmask, &sig) == -1)) {
|
|
||||||
DPRINTF(E_FATAL,L_MAIN,"Error waiting for signals. Aborting\n");
|
|
||||||
} else {
|
|
||||||
/* process the signal */
|
|
||||||
switch(sig) {
|
|
||||||
case SIGCLD:
|
|
||||||
DPRINTF(E_LOG,L_MAIN,"Got CLD signal. Reaping\n");
|
|
||||||
while (wait3(&status, WNOHANG, NULL) > 0) {
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case SIGTERM:
|
|
||||||
case SIGINT:
|
|
||||||
DPRINTF(E_LOG,L_MAIN,"Got shutdown signal. Notifying daap server.\n");
|
|
||||||
config.stop=1;
|
|
||||||
return NULL;
|
|
||||||
break;
|
|
||||||
case SIGHUP:
|
|
||||||
DPRINTF(E_LOG,L_MAIN,"Got HUP signal. Notifying daap server.\n");
|
|
||||||
/* if we can't reload, it keeps the old config file,
|
|
||||||
* so no real damage */
|
|
||||||
conf_reload();
|
|
||||||
err_reopen();
|
|
||||||
|
|
||||||
config.reload=1;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
DPRINTF(E_LOG,L_MAIN,"What am I doing here?\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Block signals, then start the signal handler. The
|
* Block signals, then start the signal handler. The
|
||||||
* signal handler started by spawning a new thread on
|
* signal handler started by spawning a new thread on
|
||||||
@ -394,28 +434,19 @@ void *_os_signal_handler(void *arg) {
|
|||||||
*
|
*
|
||||||
* \returns 0 on success, -1 on failure with errno set
|
* \returns 0 on success, -1 on failure with errno set
|
||||||
*/
|
*/
|
||||||
int _os_start_signal_handler(pthread_t *handler_tid) {
|
int _os_start_signal_handler() {
|
||||||
int error;
|
|
||||||
sigset_t set;
|
sigset_t set;
|
||||||
|
|
||||||
if((sigemptyset(&set) == -1) ||
|
if((sigemptyset(&set) == -1) ||
|
||||||
(sigaddset(&set,SIGINT) == -1) ||
|
(sigaddset(&set,SIGINT) == -1) ||
|
||||||
(sigaddset(&set,SIGHUP) == -1) ||
|
(sigaddset(&set,SIGHUP) == -1) ||
|
||||||
(sigaddset(&set,SIGCLD) == -1) ||
|
(sigaddset(&set,SIGCLD) == -1) ||
|
||||||
(sigaddset(&set,SIGTERM) == -1) ||
|
(sigaddset(&set,SIGTERM) == -1) ||
|
||||||
(sigprocmask(SIG_BLOCK, &set, NULL) == -1)) {
|
(sigprocmask(SIG_BLOCK, &set, NULL) == -1)) {
|
||||||
DPRINTF(E_LOG,L_MAIN,"Error setting signal set\n");
|
DPRINTF(E_LOG,L_MAIN,"Error setting signal set\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if((error=pthread_create(handler_tid, NULL, _os_signal_handler, NULL))) {
|
|
||||||
errno=error;
|
|
||||||
DPRINTF(E_LOG,L_MAIN,"Error creating signal_handler thread\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* we'll not detach this... let's join it */
|
|
||||||
//pthread_detach(handler_tid);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -428,8 +459,6 @@ int _os_start_signal_handler(pthread_t *handler_tid) {
|
|||||||
_os_pidfile = file;
|
_os_pidfile = file;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* load a shared library
|
* load a shared library
|
||||||
*
|
*
|
||||||
@ -467,16 +496,16 @@ int os_islocaladdr(char *hostaddr) {
|
|||||||
|
|
||||||
if(strncmp(hostaddr,"127.",4) == 0)
|
if(strncmp(hostaddr,"127.",4) == 0)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MAC
|
#ifdef MAC
|
||||||
char *os_apppath(char *parm) {
|
char *os_apppath(char *parm) {
|
||||||
CFURLRef pluginRef = CFBundleCopyBundleURL(CFBundleGetMainBundle());
|
CFURLRef pluginRef = CFBundleCopyBundleURL(CFBundleGetMainBundle());
|
||||||
CFStringRef macPath = CFURLCopyFileSystemPath(pluginRef,
|
CFStringRef macPath = CFURLCopyFileSystemPath(pluginRef,
|
||||||
kCFURLPOSIXPathStyle);
|
kCFURLPOSIXPathStyle);
|
||||||
const char *pathPtr = CFStringGetCStringPtr(macPath,
|
const char *pathPtr = CFStringGetCStringPtr(macPath,
|
||||||
CFStringGetSystemEncoding());
|
CFStringGetSystemEncoding());
|
||||||
|
|
||||||
return strdup(pathPtr);
|
return strdup(pathPtr);
|
||||||
@ -494,7 +523,7 @@ char *os_apppath(char *parm) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* stat wrapper
|
* stat wrapper
|
||||||
*/
|
*/
|
||||||
int os_stat(const char *path, struct stat *sb) {
|
int os_stat(const char *path, struct stat *sb) {
|
||||||
|
@ -142,6 +142,14 @@ void _os_phandle_dump(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* wait for signals
|
||||||
|
*
|
||||||
|
* don't care about signals on win32, so we'll just sleep
|
||||||
|
*/
|
||||||
|
void os_wait(int seconds) {
|
||||||
|
Sleep(seconds * 1000);
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* shutdown the system-specific stuff started in os_init.
|
* shutdown the system-specific stuff started in os_init.
|
||||||
*/
|
*/
|
||||||
@ -193,6 +201,12 @@ extern int os_chown(char *path, char *user) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int os_signal_server(int what) {
|
||||||
|
/* this could really control the service somehow */
|
||||||
|
fprintf(stderr,"This function is unimplemented on win32\n");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
int os_register(void) {
|
int os_register(void) {
|
||||||
service_register();
|
service_register();
|
||||||
elog_register();
|
elog_register();
|
||||||
|
6
src/os.h
6
src/os.h
@ -22,10 +22,14 @@
|
|||||||
#ifndef _OS_H_
|
#ifndef _OS_H_
|
||||||
#define _OS_H_
|
#define _OS_H_
|
||||||
|
|
||||||
|
#define S_STOP 0
|
||||||
|
#define S_SCAN 1
|
||||||
|
#define S_FULL 2
|
||||||
|
|
||||||
/* backgrounding, signal handling, etc */
|
/* backgrounding, signal handling, etc */
|
||||||
extern int os_init(int foreground, char *runas);
|
extern int os_init(int foreground, char *runas);
|
||||||
extern void os_deinit(void);
|
extern void os_deinit(void);
|
||||||
|
extern void os_wait(int seconds);
|
||||||
|
|
||||||
/* system native logging functions */
|
/* system native logging functions */
|
||||||
extern int os_opensyslog(void);
|
extern int os_opensyslog(void);
|
||||||
@ -43,7 +47,7 @@ extern int os_stat(const char *path, struct stat *sb);
|
|||||||
extern int os_lstat(const char *path, struct stat *sb);
|
extern int os_lstat(const char *path, struct stat *sb);
|
||||||
extern int os_islocaladdr(char *hostaddr);
|
extern int os_islocaladdr(char *hostaddr);
|
||||||
extern char *os_apppath(char *parm);
|
extern char *os_apppath(char *parm);
|
||||||
|
extern int os_signal_server(int what); /* signal a running server */
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
# include "os-win32.h"
|
# include "os-win32.h"
|
||||||
|
@ -476,3 +476,10 @@ void _util_mutex_init(void) {
|
|||||||
|
|
||||||
pthread_mutex_unlock(&util_mutex);
|
pthread_mutex_unlock(&util_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG_MEM
|
||||||
|
void *util_malloc(char *file, char *line, size_t size);
|
||||||
|
void *util_calloc(char *file, char *line, size_t count, size_t size);
|
||||||
|
void *util_realloc(char *file, char *line, void *ptr, size_t size);
|
||||||
|
void util_free(void *ptr);
|
||||||
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user