Commit 856361ff authored by Havoc Pennington's avatar Havoc Pennington

2003-04-06 Havoc Pennington <hp@pobox.com>

	* dbus/dbus-sysdeps.c (_dbus_become_daemon): write the pidfile
	here in the parent process, so we can return an error if it
	fails. Also, move some of the code into the child so the parent
	is less hosed if we fail midway through.

	* bus/bus.c (bus_context_new): move pidfile detection further up
	in the function, before we start overwriting sockets and such.

	* bus/messagebus.in: adjust this a bit, not sure if it will work.

	* configure.in: add --with-system-pid-file and --with-system-socket

2003-04-06  Colin Walters  <walters@verbum.org>

	* configure.in (DBUS_SYSTEM_PID_FILE): New variable.

	* bus/system.conf.in: Declare a pidfile.

	* bus/bus.c (bus_context_new): Test for an existing pid file, and
	create one (if appropriate).

	* bus/config-parser.c (enum ElementType) [ELEMENT_PIDFILE]: New.
	(struct BusConfigParser) [pidfile]: New.
	(element_type_to_name, merge_included, start_busconfig_child)
	(bus_config_parser_end_element, bus_config_parser_content): Handle it.
	(bus_config_parser_unref): Free it.
	(bus_config_parser_get_pidfile): New function.

	* bus/config-parser.h (_dbus_write_pid_file): Prototype.

	* dbus/dbus-errors.h (DBUS_ERROR_PIDFILE_EXISTS): New error.

	* dbus/dbus-sysdeps.c (_dbus_write_pid_file): New function.

	* dbus/dbus-sysdeps.h: Prototype it.
parent c8991b0f
2003-04-06 Havoc Pennington <hp@pobox.com>
* dbus/dbus-sysdeps.c (_dbus_become_daemon): write the pidfile
here in the parent process, so we can return an error if it
fails. Also, move some of the code into the child so the parent
is less hosed if we fail midway through.
* bus/bus.c (bus_context_new): move pidfile detection further up
in the function, before we start overwriting sockets and such.
* bus/messagebus.in: adjust this a bit, not sure if it will work.
* configure.in: add --with-system-pid-file and --with-system-socket
2003-04-06 Colin Walters <walters@verbum.org>
* configure.in (DBUS_SYSTEM_PID_FILE): New variable.
* bus/system.conf.in: Declare a pidfile.
* bus/bus.c (bus_context_new): Test for an existing pid file, and
create one (if appropriate).
* bus/config-parser.c (enum ElementType) [ELEMENT_PIDFILE]: New.
(struct BusConfigParser) [pidfile]: New.
(element_type_to_name, merge_included, start_busconfig_child)
(bus_config_parser_end_element, bus_config_parser_content): Handle it.
(bus_config_parser_unref): Free it.
(bus_config_parser_get_pidfile): New function.
* bus/config-parser.h (_dbus_write_pid_file): Prototype.
* dbus/dbus-errors.h (DBUS_ERROR_PIDFILE_EXISTS): New error.
* dbus/dbus-sysdeps.c (_dbus_write_pid_file): New function.
* dbus/dbus-sysdeps.h: Prototype it.
2003-04-06 Havoc Pennington <hp@pobox.com>
* bus/bus.c (bus_context_new): print the address in here, rather
......
......@@ -306,7 +306,7 @@ bus_context_new (const DBusString *config_file,
DBusList **addresses;
BusConfigParser *parser;
DBusString full_address;
const char *user;
const char *user, *pidfile;
char **auth_mechanisms;
DBusList **auth_mechanisms_list;
int len;
......@@ -333,6 +333,31 @@ bus_context_new (const DBusString *config_file,
parser = bus_config_load (config_file, error);
if (parser == NULL)
goto failed;
/* Check for an existing pid file. Of course this is a race;
* we'd have to use fcntl() locks on the pid file to
* avoid that. But we want to check for the pid file
* before overwriting any existing sockets, etc.
*/
pidfile = bus_config_parser_get_pidfile (parser);
if (pidfile != NULL)
{
DBusString u;
DBusStat stbuf;
DBusError tmp_error;
dbus_error_init (&tmp_error);
_dbus_string_init_const (&u, pidfile);
if (_dbus_stat (&u, &stbuf, &tmp_error))
{
dbus_set_error (error, DBUS_ERROR_FAILED,
"The pid file \"%s\" exists, if the message bus is not running, remove this file",
pidfile);
dbus_error_free (&tmp_error);
goto failed;
}
}
context = dbus_new0 (BusContext, 1);
if (context == NULL)
......@@ -587,9 +612,27 @@ bus_context_new (const DBusString *config_file,
/* Now become a daemon if appropriate */
if (bus_config_parser_get_fork (parser))
{
if (!_dbus_become_daemon (error))
DBusString u;
if (pidfile)
_dbus_string_init_const (&u, pidfile);
if (!_dbus_become_daemon (pidfile ? &u : NULL, error))
goto failed;
}
else
{
/* Need to write PID file for ourselves, not for the child process */
if (pidfile != NULL)
{
DBusString u;
_dbus_string_init_const (&u, pidfile);
if (!_dbus_write_pid_file (&u, _dbus_getpid (), error))
goto failed;
}
}
bus_config_parser_unref (parser);
_dbus_string_free (&full_address);
......
......@@ -40,6 +40,7 @@ typedef enum
ELEMENT_ALLOW,
ELEMENT_DENY,
ELEMENT_FORK,
ELEMENT_PIDFILE,
ELEMENT_SERVICEDIR,
ELEMENT_INCLUDEDIR,
ELEMENT_TYPE
......@@ -94,6 +95,8 @@ struct BusConfigParser
DBusList *service_dirs; /**< Directories to look for services in */
unsigned int fork : 1; /**< TRUE to fork into daemon mode */
char *pidfile;
};
static const char*
......@@ -123,6 +126,8 @@ element_type_to_name (ElementType type)
return "deny";
case ELEMENT_FORK:
return "fork";
case ELEMENT_PIDFILE:
return "pidfile";
case ELEMENT_SERVICEDIR:
return "servicedir";
case ELEMENT_INCLUDEDIR:
......@@ -222,6 +227,13 @@ merge_included (BusConfigParser *parser,
if (included->fork)
parser->fork = TRUE;
if (included->pidfile != NULL)
{
dbus_free (parser->pidfile);
parser->pidfile = included->pidfile;
included->pidfile = NULL;
}
while ((link = _dbus_list_pop_first_link (&included->listen_on)))
_dbus_list_append_link (&parser->listen_on, link);
......@@ -284,6 +296,7 @@ bus_config_parser_unref (BusConfigParser *parser)
dbus_free (parser->user);
dbus_free (parser->bus_type);
dbus_free (parser->pidfile);
_dbus_list_foreach (&parser->listen_on,
(DBusForeachFunction) dbus_free,
......@@ -497,6 +510,19 @@ start_busconfig_child (BusConfigParser *parser,
parser->fork = TRUE;
return TRUE;
}
else if (strcmp (element_name, "pidfile") == 0)
{
if (!check_no_attributes (parser, "pidfile", attribute_names, attribute_values, error))
return FALSE;
if (push_element (parser, ELEMENT_PIDFILE) == NULL)
{
BUS_SET_OOM (error);
return FALSE;
}
return TRUE;
}
else if (strcmp (element_name, "listen") == 0)
......@@ -770,6 +796,7 @@ bus_config_parser_end_element (BusConfigParser *parser,
case ELEMENT_USER:
case ELEMENT_TYPE:
case ELEMENT_LISTEN:
case ELEMENT_PIDFILE:
case ELEMENT_AUTH:
case ELEMENT_SERVICEDIR:
case ELEMENT_INCLUDEDIR:
......@@ -1004,6 +1031,20 @@ bus_config_parser_content (BusConfigParser *parser,
return FALSE;
}
case ELEMENT_PIDFILE:
{
char *s;
e->had_content = TRUE;
if (!_dbus_string_copy_data (content, &s))
goto nomem;
dbus_free (parser->pidfile);
parser->pidfile = s;
}
break;
case ELEMENT_INCLUDE:
{
DBusString full_path;
......@@ -1222,6 +1263,12 @@ bus_config_parser_get_fork (BusConfigParser *parser)
return parser->fork;
}
const char *
bus_config_parser_get_pidfile (BusConfigParser *parser)
{
return parser->pidfile;
}
#ifdef DBUS_BUILD_TESTS
#include <stdio.h>
......
......@@ -60,6 +60,7 @@ const char* bus_config_parser_get_type (BusConfigParser *parser);
DBusList** bus_config_parser_get_addresses (BusConfigParser *parser);
DBusList** bus_config_parser_get_mechanisms (BusConfigParser *parser);
dbus_bool_t bus_config_parser_get_fork (BusConfigParser *parser);
const char* bus_config_parser_get_pidfile (BusConfigParser *parser);
DBusList** bus_config_parser_get_service_dirs (BusConfigParser *parser);
/* Loader functions (backended off one of the XML parsers). Returns a
......
......@@ -7,7 +7,7 @@
# and other messages. See http://www.freedesktop.org/software/dbus/
#
# processname: dbus-daemon-1
# pidfile: @EXPANDED_LOCALSTATEDIR@/messagebus.pid
# pidfile: @DBUS_SYSTEM_PID_FILE@
#
# Sanity checks.
......@@ -20,7 +20,7 @@ RETVAL=0
start() {
echo -n $"Starting system message bus: "
daemon dbus-daemon-1 --system
daemon --check messagebus dbus-daemon-1 --system
RETVAL=$?
echo
[ $RETVAL -eq 0 ] && touch @EXPANDED_LOCALSTATEDIR@/lock/subsys/messagebus
......@@ -28,7 +28,11 @@ start() {
stop() {
echo -n $"Stopping system message bus: "
killproc messagebus
## we don't want to kill all the per-user dbus-daemon-1, we want
## to use the pid file *only*; because we use the fake nonexistent
## program name "messagebus" that should be safe-ish
killproc messagebus -TERM
RETVAL=$?
echo
if [ $RETVAL -eq 0 ]; then
......@@ -59,7 +63,7 @@ case "$1" in
fi
;;
reload)
killproc messagebus -HUP
echo "Message bus can't reload its configuration, you have to restart it"
RETVAL=$?
;;
*)
......
......@@ -20,11 +20,14 @@
<!-- Fork into daemon mode -->
<fork/>
<!-- Write a pid file -->
<pidfile>@DBUS_SYSTEM_PID_FILE@</pidfile>
<!-- Only allow socket-credentials-based authentication -->
<auth>EXTERNAL</auth>
<!-- Only listen on a local socket -->
<listen>unix:path=@EXPANDED_LOCALSTATEDIR@/@DBUS_SYSTEM_SOCKET@</listen>
<listen>unix:path=@DBUS_SYSTEM_SOCKET@</listen>
<policy context="default">
<!-- Deny everything then punch holes -->
......
......@@ -35,6 +35,8 @@ AC_ARG_WITH(xml, [ --with-xml=[libxml/expat] XML library to use]
AC_ARG_WITH(init-scripts, [ --with-init-scripts=[redhat] Style of init scripts to install])
AC_ARG_WITH(session-socket-dir, [ --with-session-socket-dir=[dirname] Where to put sockets for the per-login-session message bus])
AC_ARG_WITH(test-socket-dir, [ --with-test-socket-dir=[dirname] Where to put sockets for make check])
AC_ARG_WITH(system-pid-file, [ --with-system-pid-file=[pidfile] PID file for systemwide daemon])
AC_ARG_WITH(system-socket, [ --with-system-socket=[filename] UNIX domain socket for systemwide daemon])
dnl DBUS_BUILD_TESTS controls unit tests built in to .c files
dnl and also some stuff in the test/ subdir
......@@ -385,12 +387,9 @@ dnl Qt flags
AC_SUBST(DBUS_QT_CXXFLAGS)
AC_SUBST(DBUS_QT_LIBS)
##### Set up location for system bus socket
## name of socket relative to localstatedir
DBUS_SYSTEM_SOCKET=run/dbus/system_bus_socket
AC_SUBST(DBUS_SYSTEM_SOCKET)
#### find the actual value for $prefix that we'll end up with
## (I know this is broken and should be done in the Makefile, but
## that's a major pain and almost nobody actually seems to care)
REAL_PREFIX=
if test "x$prefix" = "xNONE"; then
REAL_PREFIX=$ac_default_prefix
......@@ -421,18 +420,45 @@ EXPANDED_BINDIR=`eval echo $BINDIR_TMP`
prefix=$old_prefix
AC_SUBST(EXPANDED_BINDIR)
#### Check our operating system
operating_system=unknown
if test -f /etc/redhat-release || test -f $EXPANDED_SYSCONFDIR/redhat-release ; then
operating_system=redhat
fi
#### Sort out init scripts
if test x$with_init_scripts = x; then
if test -f /etc/redhat-release || test -f $EXPANDED_SYSCONFDIR/redhat-release ; then
with_init_scripts=redhat
else
with_init_scripts=none
fi
if test xredhat = x$operating_system ; then
with_init_scripts=redhat
else
with_init_scripts=none
fi
fi
AM_CONDITIONAL(DBUS_INIT_SCRIPTS_RED_HAT, test x$with_init_scripts = xredhat)
##### Set up location for system bus socket
if ! test -z "$with_system_socket"; then
DBUS_SYSTEM_SOCKET=$with_system_socket
else
DBUS_SYSTEM_SOCKET=${EXPANDED_LOCALSTATEDIR}/run/dbus/system_bus_socket
fi
AC_SUBST(DBUS_SYSTEM_SOCKET)
#### Set up the pid file
if ! test -z "$with_system_pid_file"; then
DBUS_SYSTEM_PID_FILE=$with_system_pid_file
elif test x$operating_system = xredhat ; then
DBUS_SYSTEM_PID_FILE=${EXPANDED_LOCALSTATEDIR}/run/messagebus.pid
else
DBUS_SYSTEM_PID_FILE=${EXPANDED_LOCALSTATEDIR}/run/dbus/pid
fi
AC_SUBST(DBUS_SYSTEM_PID_FILE)
#### Tell tests where to find certain stuff in builddir
ABSOLUTE_TOP_BUILDDIR=`cd ${ac_top_builddir}. && pwd`
......@@ -512,7 +538,8 @@ echo "
Building GLib bindings: ${have_glib}
Using XML parser: ${with_xml}
Init scripts style: ${with_init_scripts}
System bus socket: ${EXPANDED_LOCALSTATEDIR}/${DBUS_SYSTEM_SOCKET}
System bus socket: ${DBUS_SYSTEM_SOCKET}
System bus PID file: ${DBUS_SYSTEM_PID_FILE}
Session bus socket dir: ${DBUS_SESSION_SOCKET_DIR}
'make check' socket dir: ${TEST_SOCKET_DIR}
"
......
INCLUDES=-I$(top_srcdir) $(DBUS_CLIENT_CFLAGS) -DDBUS_COMPILATION \
-DDBUS_SYSTEM_BUS_PATH=\""@EXPANDED_LOCALSTATEDIR@/@DBUS_SYSTEM_SOCKET@"\"
-DDBUS_SYSTEM_BUS_PATH=\""@DBUS_SYSTEM_SOCKET@"\"
dbusincludedir=$(includedir)/dbus-1.0/dbus
......
......@@ -1700,6 +1700,15 @@ _dbus_string_append_our_uid (DBusString *str)
return _dbus_string_append_int (str, getuid ());
}
/**
* Gets our process ID
* @returns process ID
*/
unsigned long
_dbus_getpid (void)
{
return getpid ();
}
_DBUS_DEFINE_GLOBAL_LOCK (atomic);
......@@ -2930,17 +2939,17 @@ _dbus_print_backtrace (void)
/**
* Does the chdir, fork, setsid, etc. to become a daemon process.
*
* @param pidfile #NULL, or pidfile to create
* @param error return location for errors
* @returns #FALSE on failure
*/
dbus_bool_t
_dbus_become_daemon (DBusError *error)
_dbus_become_daemon (const DBusString *pidfile,
DBusError *error)
{
const char *s;
pid_t child_pid;
/* This is so we don't prevent unmounting of devices. We divert
* all messages to syslog
*/
if (chdir ("/") < 0)
{
dbus_set_error (error, DBUS_ERROR_FAILED,
......@@ -2948,29 +2957,7 @@ _dbus_become_daemon (DBusError *error)
return FALSE;
}
s = _dbus_getenv ("DBUS_DEBUG_OUTPUT");
if (s == NULL || *s == '\0')
{
int dev_null_fd;
/* silently ignore failures here, if someone
* doesn't have /dev/null we may as well try
* to continue anyhow
*/
dev_null_fd = open ("/dev/null", O_RDWR);
if (dev_null_fd >= 0)
{
dup2 (dev_null_fd, 0);
dup2 (dev_null_fd, 1);
dup2 (dev_null_fd, 2);
}
}
/* Get a predictable umask */
umask (022);
switch (fork ())
switch ((child_pid = fork ()))
{
case -1:
dbus_set_error (error, _dbus_error_from_errno (errno),
......@@ -2978,10 +2965,41 @@ _dbus_become_daemon (DBusError *error)
return FALSE;
break;
case 0:
case 0:
s = _dbus_getenv ("DBUS_DEBUG_OUTPUT");
if (s == NULL || *s == '\0')
{
int dev_null_fd;
/* silently ignore failures here, if someone
* doesn't have /dev/null we may as well try
* to continue anyhow
*/
dev_null_fd = open ("/dev/null", O_RDWR);
if (dev_null_fd >= 0)
{
dup2 (dev_null_fd, 0);
dup2 (dev_null_fd, 1);
dup2 (dev_null_fd, 2);
}
}
/* Get a predictable umask */
umask (022);
break;
default:
if (pidfile)
{
if (!_dbus_write_pid_file (pidfile,
child_pid,
error))
{
kill (child_pid, SIGTERM);
return FALSE;
}
}
_exit (0);
break;
}
......@@ -2992,6 +3010,62 @@ _dbus_become_daemon (DBusError *error)
return TRUE;
}
/**
* Creates a file containing the process ID.
*
* @param filename the filename to write to
* @param pid our process ID
* @param error return location for errors
* @returns #FALSE on failure
*/
dbus_bool_t
_dbus_write_pid_file (const DBusString *filename,
unsigned long pid,
DBusError *error)
{
const char *cfilename;
int fd;
FILE *f;
cfilename = _dbus_string_get_const_data (filename);
fd = open (cfilename, O_WRONLY|O_CREAT|O_EXCL|O_BINARY, 0644);
if (fd < 0)
{
dbus_set_error (error, _dbus_error_from_errno (errno),
"Failed to open \"%s\": %s", cfilename,
_dbus_strerror (errno));
return FALSE;
}
if ((f = fdopen (fd, "w")) == NULL)
{
dbus_set_error (error, _dbus_error_from_errno (errno),
"Failed to fdopen fd %d: %s", fd, _dbus_strerror (errno));
close (fd);
return FALSE;
}
if (fprintf (f, "%lu\n", pid) < 0)
{
dbus_set_error (error, _dbus_error_from_errno (errno),
"Failed to write to \"%s\": %s", cfilename,
_dbus_strerror (errno));
return FALSE;
}
if (fclose (f) == EOF)
{
dbus_set_error (error, _dbus_error_from_errno (errno),
"Failed to close \"%s\": %s", cfilename,
_dbus_strerror (errno));
return FALSE;
}
return TRUE;
}
/**
* Changes the user and group the bus is running as.
*
......
......@@ -119,6 +119,8 @@ dbus_bool_t _dbus_get_groups (unsigned long uid,
unsigned long **group_ids,
int *n_group_ids);
unsigned long _dbus_getpid (void);
typedef int dbus_atomic_t;
dbus_atomic_t _dbus_atomic_inc (dbus_atomic_t *atomic);
......@@ -216,11 +218,14 @@ dbus_bool_t _dbus_close (int fd,
void _dbus_print_backtrace (void);
dbus_bool_t _dbus_become_daemon (DBusError *error);
dbus_bool_t _dbus_change_identity (unsigned long uid,
unsigned long gid,
DBusError *error);
dbus_bool_t _dbus_become_daemon (const DBusString *pidfile,
DBusError *error);
dbus_bool_t _dbus_write_pid_file (const DBusString *filename,
unsigned long pid,
DBusError *error);
dbus_bool_t _dbus_change_identity (unsigned long uid,
unsigned long gid,
DBusError *error);
typedef void (* DBusSignalHandler) (int sig);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment