add PID file handling to clients (including signal handling to remove the files)

This commit is contained in:
marschap
2008-01-06 17:03:51 +00:00
parent 7db002742e
commit c68e1aca72
12 changed files with 185 additions and 28 deletions
+1 -1
View File
@@ -8,7 +8,7 @@ lcdexec_SOURCES = lcdexec.c menu.c menu.h
lcdexec_LDADD = ../../shared/libLCDstuff.a
AM_CPPFLAGS = -I$(top_srcdir) -DSYSCONFDIR=\"$(sysconfdir)\"
AM_CPPFLAGS = -I$(top_srcdir) -DSYSCONFDIR=\"$(sysconfdir)\" -DPIDFILEDIR=\"$(pidfiledir)\"
EXTRA_DIST = $(sysconf_DATA)
+55 -10
View File
@@ -14,6 +14,7 @@
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/utsname.h>
#include <signal.h>
#include <time.h>
@@ -32,8 +33,12 @@
#if !defined(SYSCONFDIR)
# define SYSCONFDIR "/etc"
#endif
#if !defined(PIDFILEDIR)
# define PIDFILEDIR "/var/run"
#endif
#define DEFAULT_CONFIGFILE SYSCONFDIR "/lcdexec.conf"
#define DEFAULT_PIDFILE PIDFILEDIR "/lcdexec.pid"
/** information about a process started by lcdexec */
@@ -52,7 +57,7 @@ typedef struct ProcInfo {
char * help_text =
"lcdexec - LCDproc client to execute commands from the LCDd menu\n"
"\n"
"Copyright (c) 2002, Joris Robijn, 2006 Peter Marschall.\n"
"Copyright (c) 2002, Joris Robijn, 2006,7 Peter Marschall.\n"
"This program is released under the terms of the GNU General Public License.\n"
"\n"
"Usage: lcdexec [<options>]\n"
@@ -76,10 +81,11 @@ int port = UNSET_INT;
int foreground = FALSE;
static int report_level = UNSET_INT;
static int report_dest = UNSET_INT;
char *pidfile = NULL;
char *displayname = NULL;
char *default_shell = NULL;
/* Other variables */
/* Other global variables */
MenuEntry *main_menu = NULL; /**< pointer to the main menu */
ProcInfo *proc_queue = NULL; /**< pointer to the list of executed processes */
@@ -88,9 +94,12 @@ int lcd_hgt = 0; /**< LCD display height reported by the server */
int sock = -1; /**< socket to connect to server */
int Quit = 0; /**< indicate end of main loop */
/* Function prototypes */
static void sigchld_handler(int);
static void exit_program(int val);
static void sigchld_handler(int signal);
static int process_command_line(int argc, char **argv);
static int process_configfile(char * configfile);
static int connect_and_setup(void);
@@ -128,8 +137,30 @@ int main(int argc, char **argv)
if (daemon(1,1) != 0) {
report(RPT_ERR, "Error: daemonize failed");
}
if (pidfile != NULL) {
FILE *pidf = fopen(pidfile, "w");
if (pidf) {
fprintf(pidf, "%d\n", (int) getpid());
fclose(pidf);
} else {
fprintf(stderr, "Error creating pidfile %s: %s\n",
pidfile, strerror(errno));
return(EXIT_FAILURE);
}
}
}
/* setup signal handlers for common signals */
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
sa.sa_handler = exit_program;
sigaction(SIGINT, &sa, NULL); // Ctrl-C
sigaction(SIGTERM, &sa, NULL); // "regular" kill
sigaction(SIGHUP, &sa, NULL); // kill -HUP
sigaction(SIGKILL, &sa, NULL); // kill -9 [cannot be trapped; but ...]
/* setup signal handler for children to avoid zombies */
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART | SA_NOCLDSTOP;
@@ -138,7 +169,18 @@ int main(int argc, char **argv)
main_loop();
return 0;
exit_program(EXIT_SUCCESS);
}
static void exit_program(int val)
{
//printf("exit program\n");
Quit = 1;
sock_close(sock);
if ((foreground != TRUE) && (pidfile != NULL))
unlink(pidfile);
exit(val);
}
@@ -215,7 +257,7 @@ static int process_command_line(int argc, char **argv)
break;
case 'h':
fprintf(stderr, "%s", help_text);
exit(0);
exit(EXIT_SUCCESS);
case ':':
report(RPT_ERR, "Missing option argument for %c", optopt);
error = -1;
@@ -259,6 +301,9 @@ static int process_configfile(char *configfile)
if (foreground != TRUE) {
foreground = config_get_bool(progname, "Foreground", 0, FALSE);
}
if (pidfile == NULL) {
pidfile = strdup(config_get_string(progname, "PidFile", 0, DEFAULT_PIDFILE));
}
if ((tmp = config_get_string(progname, "DisplayName", 0, NULL)) != NULL)
displayname = strdup(tmp);
@@ -453,8 +498,7 @@ static int process_response(char *str)
else if (strcmp(argv[0], "bye") == 0) {
// TODO: make it better
report(RPT_INFO, "Server said: \"%s\"", str);
sock_close(sock);
exit(EXIT_SUCCESS);
exit_program(EXIT_SUCCESS);
}
else if (strcmp(argv[0], "huh?") == 0) {
/* Report errors */
@@ -535,7 +579,7 @@ static int exec_command(MenuEntry *cmd)
case 0:
/* We're the child: execute the command */
execve(argv[0], (char **) argv, envp);
exit(0);
exit(EXIT_SUCCESS);
break;
default:
/* We're the parent: setup the ProcInfo structure */
@@ -644,7 +688,7 @@ static int main_loop(void)
int status_delay = 0;
/* Continuously check if we get a menu event... */
while ((num_bytes = sock_recv_string(sock, buf, sizeof(buf)-1)) >= 0) {
while (!Quit && ((num_bytes = sock_recv_string(sock, buf, sizeof(buf)-1)) >= 0)) {
if (num_bytes == 0) {
ProcInfo *p;
@@ -690,7 +734,8 @@ static int main_loop(void)
}
}
report(RPT_ERR, "Server disconnected (or connection error)");
if (!Quit)
report(RPT_ERR, "Server disconnected (or connection error)");
return 0;
}
+3
View File
@@ -17,6 +17,9 @@ ReportToSyslog=false
# run in foreground [default: false; legal: true, false]
Foreground=false
# PidFile location when running as daemon [default: /var/run/lcdexec.pid]
#PidFile=/var/run/lcdexec.pid
# shell to use for executing programsi
# [default: $SHELL or /bin/sh; legal: any shell that understands: -c COMMAND]
#Shell=/bin/sh
+1 -1
View File
@@ -12,7 +12,7 @@ if DARWIN
AM_LDFLAGS = -framework CoreFoundation -framework IOKit
endif
AM_CPPFLAGS = -I$(top_srcdir) -DSYSCONFDIR=\"$(sysconfdir)\"
AM_CPPFLAGS = -I$(top_srcdir) -DSYSCONFDIR=\"$(sysconfdir)\" -DPIDFILEDIR=\"$(pidfiledir)\"
EXTRA_DIST = $(sysconf_DATA)
+3
View File
@@ -17,6 +17,9 @@ ReportToSyslog=false
# run in foreground [default: false; legal: true, false]
#Foreground=true
# PidFile location when running as daemon [default: /var/run/lcdproc.pid]
#PidFile=/var/run/lcdproc.pid
# slow down initial announcement of modes (in 1/100s)
#delay=2
+26 -5
View File
@@ -70,11 +70,15 @@ static int process_configfile(char *cfgfile);
#if !defined(SYSCONFDIR)
# define SYSCONFDIR "/etc"
#endif
#if !defined(PIDFILEDIR)
# define PIDFILEDIR "/var/run"
#endif
#define UNSET_INT -1
#define UNSET_STR "\01"
#define DEFAULT_SERVER "127.0.0.1"
#define DEFAULT_CONFIGFILE SYSCONFDIR "/lcdproc.conf"
#define DEFAULT_PIDFILE PIDFILEDIR "/lcdproc.pid"
#define DEFAULT_REPORTDEST RPT_DEST_STDERR
#define DEFAULT_REPORTLEVEL RPT_WARNING
@@ -111,6 +115,7 @@ int port = LCDPORT;
int foreground = FALSE;
static int report_level = UNSET_INT;
static int report_dest = UNSET_INT;
char *pidfile = NULL;
char *configfile = NULL;
char *displayname = NULL;
@@ -243,7 +248,7 @@ main(int argc, char **argv)
/* Read config file*/
cfgresult = process_configfile(configfile);
if (cfgresult < 0) {
fprintf(stderr, "Error reading config file");
fprintf(stderr, "Error reading config file\n");
exit(EXIT_FAILURE);
}
@@ -303,9 +308,22 @@ main(int argc, char **argv)
if (foreground != TRUE) {
if (daemon(1,0) != 0) {
fprintf(stderr, "Error: daemonize failed");
fprintf(stderr, "Error: daemonize failed\n");
return(EXIT_FAILURE);
}
if (pidfile != NULL) {
FILE *pidf = fopen(pidfile, "w");
if (pidf) {
fprintf(pidf, "%d\n", (int) getpid());
fclose(pidf);
} else {
fprintf(stderr, "Error creating pidfile %s: %s\n",
pidfile, strerror(errno));
return(EXIT_FAILURE);
}
}
}
// Init the status gatherers...
@@ -314,10 +332,8 @@ main(int argc, char **argv)
// And spew stuff!
main_loop();
// Clean up
// Clean up & exit
exit_program(EXIT_SUCCESS);
return(0);
}
@@ -372,6 +388,9 @@ process_configfile(char *configfile)
if (foreground != TRUE) {
foreground = config_get_bool(progname, "Foreground", 0, FALSE);
}
if (pidfile == NULL) {
pidfile = strdup(config_get_string(progname, "PidFile", 0, DEFAULT_PIDFILE));
}
if (islow < 0) {
islow = config_get_int(progname, "Delay", 0, -1);
}
@@ -455,6 +474,8 @@ exit_program(int val)
Quit = 1;
sock_close(sock);
mode_close();
if ((foreground != TRUE) && (pidfile != NULL))
unlink(pidfile);
exit(val);
}
+1 -1
View File
@@ -12,7 +12,7 @@ if DARWIN
AM_LDFLAGS = -framework CoreFoundation -framework IOKit
endif
AM_CPPFLAGS = -I$(top_srcdir) -DSYSCONFDIR=\"$(sysconfdir)\"
AM_CPPFLAGS = -I$(top_srcdir) -DSYSCONFDIR=\"$(sysconfdir)\" -DPIDFILEDIR=\"$(pidfiledir)\"
#AM_CFLAGS = -g -O0
#AM_LDFLAGS = -g
+9 -1
View File
@@ -33,7 +33,7 @@ static int read_connect_string(void);
static int split(char *str, char delim, char *parts[], int maxparts);
int connect_and_setup(void)
int setup_connection(void)
{
char buf[200];
int i;
@@ -83,6 +83,14 @@ int connect_and_setup(void)
}
int teardown_connection(void)
{
sock_close(sock);
return 0;
}
static int read_connect_string(void)
{
char buf[8192];
+2 -1
View File
@@ -4,7 +4,8 @@
extern char *address;
extern int port;
int connect_and_setup(void);
int setup_connection(void);
int teardown_connection(void);
int read_response(char *str, int maxsize);
int process_response(char *str);
int update_display(void);
+57 -8
View File
@@ -14,6 +14,7 @@
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <signal.h>
#include <fcntl.h>
#include <errno.h>
@@ -30,8 +31,12 @@
#if !defined(SYSCONFDIR)
# define SYSCONFDIR "/etc"
#endif
#if !defined(PIDFILEDIR)
# define PIDFILEDIR "/var/run"
#endif
#define DEFAULT_CONFIGFILE SYSCONFDIR "/lcdvc.conf"
#define DEFAULT_PIDFILE PIDFILEDIR "/lcdvc.pid"
char *help_text =
@@ -50,9 +55,6 @@ char *help_text =
" -s <0|1> Report to syslog (1) or stderr (0, default)\n"
" -h Show this help\n";
char *progname = "lcdvc";
char *configfile = UNSET_STR;
/* Variables set by config */
int foreground = FALSE;
static int report_level = UNSET_INT;
@@ -61,7 +63,15 @@ char *vcsa_device = UNSET_STR;
char *vcs_device = UNSET_STR;
char *keys[4];
/* Other global variables */
char *progname = "lcdvc";
char *pidfile = NULL;
char *configfile = UNSET_STR;
int Quit = 0; /**< indicate end of main loop */
/* Function prototypes */
static void exit_program(int val);
static int process_command_line(int argc, char **argv);
static int process_configfile(char *configfile);
static int main_loop(void);
@@ -70,6 +80,7 @@ static int main_loop(void);
int main(int argc, char **argv)
{
int e = 0;
struct sigaction sa;
CHAIN( e, process_command_line( argc, argv ));
if (strcmp( configfile, UNSET_STR ) == 0) {
@@ -83,18 +94,51 @@ int main(int argc, char **argv)
set_reporting( progname, report_level, report_dest );
CHAIN( e, open_vcs() );
CHAIN( e, connect_and_setup() );
CHAIN( e, setup_connection() );
CHAIN_END( e );
if (foreground != TRUE) {
if (daemon(1,1) != 0) {
report(RPT_ERR, "Error: daemonize failed");
}
if (pidfile != NULL) {
FILE *pidf = fopen(pidfile, "w");
if (pidf) {
fprintf(pidf, "%d\n", (int) getpid());
fclose(pidf);
} else {
fprintf(stderr, "Error creating pidfile %s: %s\n",
pidfile, strerror(errno));
return(EXIT_FAILURE);
}
}
}
/* setup signal handlers for common signals */
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
sa.sa_handler = exit_program;
sigaction(SIGINT, &sa, NULL); // Ctrl-C
sigaction(SIGTERM, &sa, NULL); // "regular" kill
sigaction(SIGHUP, &sa, NULL); // kill -HUP
sigaction(SIGKILL, &sa, NULL); // kill -9 [cannot be trapped; but ...]
main_loop();
return 0;
exit_program(EXIT_SUCCESS);
}
static void exit_program(int val)
{
//printf("exit program\n");
Quit = 1;
teardown_connection();
if ((foreground != TRUE) && (pidfile != NULL))
unlink(pidfile);
exit(val);
}
@@ -113,7 +157,7 @@ static int process_command_line(int argc, char **argv)
switch (c) {
case 'h':
fprintf(stderr, "%s", help_text);
exit( 0 );
exit(EXIT_SUCCESS);
case 'c':
configfile = strdup(optarg);
break;
@@ -194,6 +238,10 @@ static int process_configfile(char *configfile)
if (foreground != TRUE) {
foreground = config_get_bool(progname, "Foreground", 0, FALSE);
}
if (pidfile == NULL) {
pidfile = strdup(config_get_string(progname, "PidFile", 0, DEFAULT_PIDFILE));
}
vcs_device = strdup(config_get_string(progname, "vcsDevice", 0, "/dev/vcs"));
vcsa_device = strdup(config_get_string(progname, "vcsaDevice", 0, "/dev/vcsa"));
@@ -214,7 +262,7 @@ static int main_loop(void)
/* Continuously check if we get a menu event... */
while ((num_bytes = read_response(buf, sizeof(buf)-1)) >= 0) {
while (!Quit && ((num_bytes = read_response(buf, sizeof(buf)-1)) >= 0)) {
if (num_bytes != 0) {
process_response(buf);
}
@@ -233,7 +281,8 @@ static int main_loop(void)
}
}
report(RPT_WARNING, "Server disconnected %d", num_bytes);
if (!Quit)
report(RPT_WARNING, "Server disconnected %d", num_bytes);
return 0;
}
+3
View File
@@ -18,6 +18,9 @@
# run in foreground [default: false; legal: true, false]
#Foreground=false
# PidFile location when running as daemon [default: /var/run/lcdvc.pid]
#PidFile=/var/run/lcdvc.pid
# Keys to move the visible area around the screen.
#UpKey=Up
#DownKey=Down
+24
View File
@@ -273,6 +273,30 @@ dnl Select drivers to build
LCD_DRIVERS_SELECT
# directory for PID files
pidfiledir=/var/run
# make sure the directory exists
if test ! -d $pidfiledir ; then
pidfiledir=`eval echo ${sysconfdir}`
case $pidfiledir in
NONE/*) pidfiledir=`echo $pidfiledir | sed "s~NONE~$ac_default_prefix~"` ;;
esac
fi
AC_ARG_WITH(pidfile-dir,
[AS_HELP_STRING([--with-pidfile-dir=PATH], [specify location of pid files [/var/run]])],
[ if test -n "$withval" && test "x$withval" != "xno" && \
test "x${withval}" != "xyes"; then
pidfiledir=$withval
if test ! -d $pidfiledir ; then
AC_MSG_WARN([** no $pidfiledir directory on this system **])
fi
fi ]
)
AC_SUBST(pidfiledir)
# Features applicable to the server
AC_ARG_ENABLE(seamless-hbars,
[AS_HELP_STRING([--enable-seamless-hbars], [no gaps in horizontal bar graphs (if HW supports it)])],