2004-07-16 19:56:36 +00:00
/***
2006-06-19 21:53:48 +00:00
This file is part of PulseAudio .
2007-01-04 13:43:45 +00:00
2007-02-13 15:35:19 +00:00
Copyright 2004 - 2006 Lennart Poettering
Copyright 2006 Pierre Ossman < ossman @ cendio . se > for Cendio AB
2006-06-19 21:53:48 +00:00
PulseAudio is free software ; you can redistribute it and / or modify
2004-11-14 14:58:54 +00:00
it under the terms of the GNU Lesser General Public License as published
2009-03-03 20:23:02 +00:00
by the Free Software Foundation ; either version 2.1 of the License ,
2004-07-16 19:56:36 +00:00
or ( at your option ) any later version .
2007-01-04 13:43:45 +00:00
2006-06-19 21:53:48 +00:00
PulseAudio is distributed in the hope that it will be useful , but
2004-07-16 19:56:36 +00:00
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 .
2007-01-04 13:43:45 +00:00
2004-11-14 14:58:54 +00:00
You should have received a copy of the GNU Lesser General Public License
2014-11-26 14:14:51 +01:00
along with PulseAudio ; if not , see < http : //www.gnu.org/licenses/>.
2004-07-16 19:56:36 +00:00
* * */
2004-07-16 19:16:42 +00:00
# ifdef HAVE_CONFIG_H
# include <config.h>
# endif
2004-07-15 19:00:42 +00:00
# include <unistd.h>
# include <errno.h>
# include <string.h>
2004-07-14 21:52:41 +00:00
# include <stdlib.h>
2004-06-11 21:30:16 +00:00
# include <stdio.h>
# include <signal.h>
2004-06-08 23:54:24 +00:00
# include <stddef.h>
2004-06-11 00:33:43 +00:00
# include <ltdl.h>
2004-11-20 23:48:18 +00:00
# include <limits.h>
2006-01-10 17:51:06 +00:00
# include <unistd.h>
2006-05-18 10:36:36 +00:00
# include <locale.h>
2006-01-10 17:51:06 +00:00
# include <sys/types.h>
2009-06-24 22:01:55 +02:00
# include <sys/stat.h>
2006-07-19 17:44:19 +00:00
2009-06-07 00:43:03 +02:00
# ifdef HAVE_SYS_MMAN_H
# include <sys/mman.h>
# endif
2006-07-20 13:16:23 +00:00
# ifdef HAVE_PWD_H
# include <pwd.h>
# endif
# ifdef HAVE_GRP_H
# include <grp.h>
# endif
2004-09-29 20:13:05 +00:00
# ifdef HAVE_LIBWRAP
# include <syslog.h>
# include <tcpd.h>
# endif
2007-10-28 19:13:50 +00:00
# ifdef HAVE_DBUS
# include <dbus/dbus.h>
# endif
2006-06-19 21:53:48 +00:00
2014-10-16 10:05:19 +01:00
# ifdef HAVE_SYSTEMD_DAEMON
# include <systemd/sd-daemon.h>
# endif
2010-01-09 11:55:15 +02:00
# include <pulse/client-conf.h>
2006-06-19 21:53:48 +00:00
# include <pulse/mainloop.h>
# include <pulse/mainloop-signal.h>
2006-07-20 00:28:18 +00:00
# include <pulse/timeval.h>
2006-06-19 21:53:48 +00:00
# include <pulse/xmalloc.h>
2011-08-10 10:30:15 +02:00
# include <pulsecore/i18n.h>
2008-09-08 17:22:27 +03:00
# include <pulsecore/lock-autospawn.h>
2011-01-04 17:03:13 +01:00
# include <pulsecore/socket.h>
2006-06-19 21:53:48 +00:00
# include <pulsecore/core-error.h>
2009-04-04 23:19:53 +03:00
# include <pulsecore/core-rtclock.h>
2011-08-18 12:32:48 +05:30
# include <pulsecore/core-scache.h>
2006-06-19 21:53:48 +00:00
# include <pulsecore/core.h>
# include <pulsecore/module.h>
# include <pulsecore/cli-command.h>
# include <pulsecore/log.h>
# include <pulsecore/core-util.h>
# include <pulsecore/sioman.h>
# include <pulsecore/cli-text.h>
# include <pulsecore/pid.h>
# include <pulsecore/random.h>
2007-10-28 19:13:50 +00:00
# include <pulsecore/macro.h>
# include <pulsecore/shm.h>
2009-04-21 22:56:08 +02:00
# include <pulsecore/memtrap.h>
2011-03-25 23:03:31 +00:00
# include <pulsecore/strlist.h>
2009-03-20 18:39:30 +02:00
# ifdef HAVE_DBUS
# include <pulsecore/dbus-shared.h>
# endif
2014-09-10 15:23:11 +02:00
# include <pulsecore/cpu.h>
2006-02-17 12:10:58 +00:00
# include "cmdline.h"
2004-09-03 20:14:23 +00:00
# include "cpulimit.h"
2004-09-17 20:06:17 +00:00
# include "daemon-conf.h"
2004-09-13 23:28:30 +00:00
# include "dumpmodules.h"
2004-09-23 15:47:11 +00:00
# include "caps.h"
2007-10-28 19:13:50 +00:00
# include "ltdl-bind-now.h"
2009-06-12 07:16:05 +03:00
# include "server-lookup.h"
2004-06-08 23:54:24 +00:00
2004-09-29 20:13:05 +00:00
# ifdef HAVE_LIBWRAP
/* Only one instance of these variables */
int allow_severity = LOG_INFO ;
int deny_severity = LOG_WARNING ;
# endif
2009-08-08 01:53:15 +02:00
# ifdef HAVE_OSS_WRAPPER
2006-05-26 17:59:39 +00:00
/* padsp looks for this symbol in the running process and disables
* itself if it finds it and it is set to 7 ( which is actually a bit
* mask ) . For details see padsp . */
int __padsp_disabled__ = 7 ;
# endif
2008-08-09 16:20:29 +02:00
static void signal_callback ( pa_mainloop_api * m , pa_signal_event * e , int sig , void * userdata ) {
2014-09-02 12:09:44 +02:00
pa_log_info ( " Got signal %s. " , pa_sig2str ( sig ) ) ;
2004-09-03 20:14:23 +00:00
switch ( sig ) {
2006-01-10 17:51:06 +00:00
# ifdef SIGUSR1
2004-09-03 20:14:23 +00:00
case SIGUSR1 :
pa_module_load ( userdata , " module-cli " , NULL ) ;
2005-01-12 18:51:38 +00:00
break ;
2006-01-10 17:51:06 +00:00
# endif
2007-01-04 13:43:45 +00:00
2006-01-10 17:51:06 +00:00
# ifdef SIGUSR2
2004-09-03 20:14:23 +00:00
case SIGUSR2 :
pa_module_load ( userdata , " module-cli-protocol-unix " , NULL ) ;
2005-01-12 18:51:38 +00:00
break ;
2006-01-10 17:51:06 +00:00
# endif
2004-09-26 17:02:26 +00:00
2006-01-10 17:51:06 +00:00
# ifdef SIGHUP
2004-09-26 17:02:26 +00:00
case SIGHUP : {
2005-01-12 18:51:38 +00:00
char * c = pa_full_status_string ( userdata ) ;
2006-02-23 02:27:19 +00:00
pa_log_notice ( " %s " , c ) ;
2005-01-12 18:51:38 +00:00
pa_xfree ( c ) ;
2004-09-26 17:02:26 +00:00
return ;
}
2006-01-10 17:51:06 +00:00
# endif
2004-09-26 17:02:26 +00:00
2004-09-03 20:14:23 +00:00
case SIGINT :
case SIGTERM :
default :
2014-09-02 12:09:44 +02:00
pa_log_info ( " Exiting. " ) ;
2015-05-21 01:31:01 +02:00
m - > quit ( m , 0 ) ;
2005-01-12 18:51:38 +00:00
break ;
2004-09-03 20:14:23 +00:00
}
2004-06-11 21:30:16 +00:00
}
2006-07-20 13:16:23 +00:00
# if defined(HAVE_PWD_H) && defined(HAVE_GRP_H)
2006-07-19 17:44:19 +00:00
static int change_user ( void ) {
struct passwd * pw ;
struct group * gr ;
int r ;
2006-07-19 23:16:02 +00:00
/* This function is called only in system-wide mode. It creates a
* runtime dir in / var / run / with proper UID / GID and drops privs
* afterwards . */
2007-01-04 13:43:45 +00:00
2006-07-19 17:44:19 +00:00
if ( ! ( pw = getpwnam ( PA_SYSTEM_USER ) ) ) {
2008-08-06 18:54:13 +02:00
pa_log ( _ ( " Failed to find user '%s'. " ) , PA_SYSTEM_USER ) ;
2006-07-19 17:44:19 +00:00
return - 1 ;
}
if ( ! ( gr = getgrnam ( PA_SYSTEM_GROUP ) ) ) {
2008-08-06 18:54:13 +02:00
pa_log ( _ ( " Failed to find group '%s'. " ) , PA_SYSTEM_GROUP ) ;
2006-07-19 17:44:19 +00:00
return - 1 ;
}
2014-09-02 12:09:44 +02:00
pa_log_info ( " Found user '%s' (UID %lu) and group '%s' (GID %lu). " ,
2006-07-19 17:44:19 +00:00
PA_SYSTEM_USER , ( unsigned long ) pw - > pw_uid ,
PA_SYSTEM_GROUP , ( unsigned long ) gr - > gr_gid ) ;
if ( pw - > pw_gid ! = gr - > gr_gid ) {
2008-08-06 18:54:13 +02:00
pa_log ( _ ( " GID of user '%s' and of group '%s' don't match. " ) , PA_SYSTEM_USER , PA_SYSTEM_GROUP ) ;
2006-07-19 17:44:19 +00:00
return - 1 ;
}
2012-06-06 01:28:16 +05:30
if ( ! pa_streq ( pw - > pw_dir , PA_SYSTEM_RUNTIME_PATH ) )
2008-08-06 18:54:13 +02:00
pa_log_warn ( _ ( " Home directory of user '%s' is not '%s', ignoring. " ) , PA_SYSTEM_USER , PA_SYSTEM_RUNTIME_PATH ) ;
2006-07-19 17:44:19 +00:00
2013-06-27 19:28:09 +02:00
if ( pa_make_secure_dir ( PA_SYSTEM_RUNTIME_PATH , 0755 , pw - > pw_uid , gr - > gr_gid , true ) < 0 ) {
2008-08-06 18:54:13 +02:00
pa_log ( _ ( " Failed to create '%s': %s " ) , PA_SYSTEM_RUNTIME_PATH , pa_cstrerror ( errno ) ) ;
2006-07-19 17:44:19 +00:00
return - 1 ;
}
2007-01-04 13:43:45 +00:00
2013-06-27 19:28:09 +02:00
if ( pa_make_secure_dir ( PA_SYSTEM_STATE_PATH , 0700 , pw - > pw_uid , gr - > gr_gid , true ) < 0 ) {
2008-08-06 18:54:13 +02:00
pa_log ( _ ( " Failed to create '%s': %s " ) , PA_SYSTEM_STATE_PATH , pa_cstrerror ( errno ) ) ;
2008-05-21 22:50:58 +00:00
return - 1 ;
}
/* We don't create the config dir here, because we don't need to write to it */
2006-07-19 17:44:19 +00:00
if ( initgroups ( PA_SYSTEM_USER , gr - > gr_gid ) ! = 0 ) {
2008-08-06 18:54:13 +02:00
pa_log ( _ ( " Failed to change group list: %s " ) , pa_cstrerror ( errno ) ) ;
2006-07-19 17:44:19 +00:00
return - 1 ;
}
# if defined(HAVE_SETRESGID)
r = setresgid ( gr - > gr_gid , gr - > gr_gid , gr - > gr_gid ) ;
# elif defined(HAVE_SETEGID)
if ( ( r = setgid ( gr - > gr_gid ) ) > = 0 )
r = setegid ( gr - > gr_gid ) ;
# elif defined(HAVE_SETREGID)
r = setregid ( gr - > gr_gid , gr - > gr_gid ) ;
# else
2008-10-19 22:25:58 +02:00
# error "No API to drop privileges"
2006-07-19 17:44:19 +00:00
# endif
if ( r < 0 ) {
2008-08-06 18:54:13 +02:00
pa_log ( _ ( " Failed to change GID: %s " ) , pa_cstrerror ( errno ) ) ;
2006-07-19 17:44:19 +00:00
return - 1 ;
}
# if defined(HAVE_SETRESUID)
r = setresuid ( pw - > pw_uid , pw - > pw_uid , pw - > pw_uid ) ;
# elif defined(HAVE_SETEUID)
if ( ( r = setuid ( pw - > pw_uid ) ) > = 0 )
r = seteuid ( pw - > pw_uid ) ;
# elif defined(HAVE_SETREUID)
r = setreuid ( pw - > pw_uid , pw - > pw_uid ) ;
# else
2008-10-19 22:25:58 +02:00
# error "No API to drop privileges"
2006-07-19 17:44:19 +00:00
# endif
if ( r < 0 ) {
2008-08-06 18:54:13 +02:00
pa_log ( _ ( " Failed to change UID: %s " ) , pa_cstrerror ( errno ) ) ;
2006-07-19 17:44:19 +00:00
return - 1 ;
}
2012-04-05 15:37:19 +03:00
pa_drop_caps ( ) ;
2008-05-15 23:34:41 +00:00
pa_set_env ( " USER " , PA_SYSTEM_USER ) ;
pa_set_env ( " USERNAME " , PA_SYSTEM_USER ) ;
pa_set_env ( " LOGNAME " , PA_SYSTEM_USER ) ;
pa_set_env ( " HOME " , PA_SYSTEM_RUNTIME_PATH ) ;
2006-07-19 17:44:19 +00:00
/* Relevant for pa_runtime_path() */
2009-09-01 00:53:49 +02:00
if ( ! getenv ( " PULSE_RUNTIME_PATH " ) )
pa_set_env ( " PULSE_RUNTIME_PATH " , PA_SYSTEM_RUNTIME_PATH ) ;
if ( ! getenv ( " PULSE_CONFIG_PATH " ) )
pa_set_env ( " PULSE_CONFIG_PATH " , PA_SYSTEM_CONFIG_PATH ) ;
if ( ! getenv ( " PULSE_STATE_PATH " ) )
pa_set_env ( " PULSE_STATE_PATH " , PA_SYSTEM_STATE_PATH ) ;
2006-07-19 17:44:19 +00:00
2014-09-02 12:09:44 +02:00
pa_log_info ( " Successfully changed user to \" " PA_SYSTEM_USER " \" . " ) ;
2006-07-19 17:44:19 +00:00
return 0 ;
}
2006-07-20 13:16:23 +00:00
# else /* HAVE_PWD_H && HAVE_GRP_H */
static int change_user ( void ) {
2008-08-06 18:54:13 +02:00
pa_log ( _ ( " System wide mode unsupported on this platform. " ) ) ;
2006-07-20 13:16:23 +00:00
return - 1 ;
}
# endif /* HAVE_PWD_H && HAVE_GRP_H */
2006-07-20 01:25:37 +00:00
# ifdef HAVE_SYS_RESOURCE_H
2007-11-21 01:30:40 +00:00
static int set_one_rlimit ( const pa_rlimit * r , int resource , const char * name ) {
2006-07-20 01:25:37 +00:00
struct rlimit rl ;
2007-10-28 19:13:50 +00:00
pa_assert ( r ) ;
2006-07-20 01:25:37 +00:00
if ( ! r - > is_set )
2007-11-21 01:30:40 +00:00
return 0 ;
2006-07-20 01:25:37 +00:00
rl . rlim_cur = rl . rlim_max = r - > value ;
2007-11-21 01:30:40 +00:00
if ( setrlimit ( resource , & rl ) < 0 ) {
2014-09-02 12:09:44 +02:00
pa_log_info ( " setrlimit(%s, (%u, %u)) failed: %s " , name , ( unsigned ) r - > value , ( unsigned ) r - > value , pa_cstrerror ( errno ) ) ;
2007-11-21 01:30:40 +00:00
return - 1 ;
}
return 0 ;
2006-07-20 01:25:37 +00:00
}
static void set_all_rlimits ( const pa_daemon_conf * conf ) {
set_one_rlimit ( & conf - > rlimit_fsize , RLIMIT_FSIZE , " RLIMIT_FSIZE " ) ;
2008-05-15 23:34:41 +00:00
set_one_rlimit ( & conf - > rlimit_data , RLIMIT_DATA , " RLIMIT_DATA " ) ;
2006-07-20 01:25:37 +00:00
set_one_rlimit ( & conf - > rlimit_stack , RLIMIT_STACK , " RLIMIT_STACK " ) ;
2008-05-15 23:34:41 +00:00
set_one_rlimit ( & conf - > rlimit_core , RLIMIT_CORE , " RLIMIT_CORE " ) ;
2009-02-26 16:48:58 +11:00
# ifdef RLIMIT_RSS
2008-05-15 23:34:41 +00:00
set_one_rlimit ( & conf - > rlimit_rss , RLIMIT_RSS , " RLIMIT_RSS " ) ;
2009-02-26 16:48:58 +11:00
# endif
2006-07-20 01:25:37 +00:00
# ifdef RLIMIT_NPROC
set_one_rlimit ( & conf - > rlimit_nproc , RLIMIT_NPROC , " RLIMIT_NPROC " ) ;
# endif
2009-01-27 00:48:53 +01:00
# ifdef RLIMIT_NOFILE
2008-05-15 23:34:41 +00:00
set_one_rlimit ( & conf - > rlimit_nofile , RLIMIT_NOFILE , " RLIMIT_NOFILE " ) ;
2009-01-27 00:48:53 +01:00
# endif
2006-07-20 01:25:37 +00:00
# ifdef RLIMIT_MEMLOCK
set_one_rlimit ( & conf - > rlimit_memlock , RLIMIT_MEMLOCK , " RLIMIT_MEMLOCK " ) ;
2008-05-15 23:34:41 +00:00
# endif
2009-01-22 01:39:54 +01:00
# ifdef RLIMIT_AS
2008-05-15 23:34:41 +00:00
set_one_rlimit ( & conf - > rlimit_as , RLIMIT_AS , " RLIMIT_AS " ) ;
2009-01-22 01:39:54 +01:00
# endif
2008-05-15 23:34:41 +00:00
# ifdef RLIMIT_LOCKS
set_one_rlimit ( & conf - > rlimit_locks , RLIMIT_LOCKS , " RLIMIT_LOCKS " ) ;
# endif
# ifdef RLIMIT_SIGPENDING
set_one_rlimit ( & conf - > rlimit_sigpending , RLIMIT_SIGPENDING , " RLIMIT_SIGPENDING " ) ;
# endif
# ifdef RLIMIT_MSGQUEUE
set_one_rlimit ( & conf - > rlimit_msgqueue , RLIMIT_MSGQUEUE , " RLIMIT_MSGQUEUE " ) ;
2006-07-20 01:25:37 +00:00
# endif
2007-11-01 00:34:43 +00:00
# ifdef RLIMIT_NICE
set_one_rlimit ( & conf - > rlimit_nice , RLIMIT_NICE , " RLIMIT_NICE " ) ;
# endif
# ifdef RLIMIT_RTPRIO
set_one_rlimit ( & conf - > rlimit_rtprio , RLIMIT_RTPRIO , " RLIMIT_RTPRIO " ) ;
# endif
2008-05-15 23:34:41 +00:00
# ifdef RLIMIT_RTTIME
set_one_rlimit ( & conf - > rlimit_rttime , RLIMIT_RTTIME , " RLIMIT_RTTIME " ) ;
# endif
2006-07-20 01:25:37 +00:00
}
# endif
2010-01-09 11:55:15 +02:00
static char * check_configured_address ( void ) {
char * default_server = NULL ;
pa_client_conf * c = pa_client_conf_new ( ) ;
2014-06-08 16:32:54 +03:00
pa_client_conf_load ( c , true , true ) ;
2010-01-09 11:55:15 +02:00
if ( c - > default_server & & * c - > default_server )
default_server = pa_xstrdup ( c - > default_server ) ;
pa_client_conf_free ( c ) ;
return default_server ;
}
2009-03-20 18:39:30 +02:00
# ifdef HAVE_DBUS
2009-06-12 07:16:05 +03:00
static pa_dbus_connection * register_dbus_name ( pa_core * c , DBusBusType bus , const char * name ) {
2009-03-20 18:39:30 +02:00
DBusError error ;
pa_dbus_connection * conn ;
dbus_error_init ( & error ) ;
2009-04-06 02:31:22 +02:00
2009-06-12 07:16:05 +03:00
if ( ! ( conn = pa_dbus_bus_get ( c , bus , & error ) ) | | dbus_error_is_set ( & error ) ) {
2009-04-06 02:31:22 +02:00
pa_log_warn ( " Unable to contact D-Bus: %s: %s " , error . name , error . message ) ;
goto fail ;
2009-03-20 18:39:30 +02:00
}
2009-06-12 07:16:05 +03:00
if ( dbus_bus_request_name ( pa_dbus_connection_get ( conn ) , name , DBUS_NAME_FLAG_DO_NOT_QUEUE , & error ) = = DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER ) {
pa_log_debug ( " Got %s! " , name ) ;
2009-04-06 02:31:22 +02:00
return conn ;
}
if ( dbus_error_is_set ( & error ) )
2009-06-12 07:16:05 +03:00
pa_log_error ( " Failed to acquire %s: %s: %s " , name , error . name , error . message ) ;
2009-04-06 02:31:22 +02:00
else
2011-08-15 14:05:50 +02:00
pa_log_error ( " D-Bus name %s already taken. " , name ) ;
2009-04-06 02:31:22 +02:00
/* PA cannot be started twice by the same user and hence we can
2009-06-12 07:16:05 +03:00
* ignore mostly the case that a name is already taken . */
2009-04-06 02:31:22 +02:00
fail :
2009-03-20 18:39:30 +02:00
if ( conn )
pa_dbus_connection_unref ( conn ) ;
dbus_error_free ( & error ) ;
2009-04-06 02:31:22 +02:00
return NULL ;
2009-03-20 18:39:30 +02:00
}
# endif
2004-06-08 23:54:24 +00:00
int main ( int argc , char * argv [ ] ) {
2006-08-19 01:20:13 +00:00
pa_core * c = NULL ;
2006-01-11 01:17:39 +00:00
pa_strbuf * buf = NULL ;
2006-08-19 01:20:13 +00:00
pa_daemon_conf * conf = NULL ;
pa_mainloop * mainloop = NULL ;
2007-01-04 13:43:45 +00:00
char * s ;
2010-01-09 11:55:15 +02:00
char * configured_address ;
2007-10-28 19:13:50 +00:00
int r = 0 , retval = 1 , d = 0 ;
2013-06-27 19:28:09 +02:00
bool valid_pid_file = false ;
bool ltdl_init = false ;
2014-10-16 10:05:19 +01:00
int n_fds = 0 , * passed_fds = NULL ;
2008-05-15 23:34:41 +00:00
const char * e ;
# ifdef HAVE_FORK
int daemon_pipe [ 2 ] = { - 1 , - 1 } ;
2011-03-24 21:27:55 +00:00
int daemon_pipe2 [ 2 ] = { - 1 , - 1 } ;
2006-01-10 17:51:06 +00:00
# endif
2008-08-09 03:49:42 +02:00
int autospawn_fd = - 1 ;
2013-06-27 19:28:09 +02:00
bool autospawn_locked = false ;
2009-04-06 02:31:22 +02:00
# ifdef HAVE_DBUS
2009-06-12 07:16:05 +03:00
pa_dbusobj_server_lookup * server_lookup = NULL ; /* /org/pulseaudio/server_lookup */
pa_dbus_connection * lookup_service_bus = NULL ; /* Always the user bus. */
pa_dbus_connection * server_bus = NULL ; /* The bus where we reserve org.pulseaudio.Server, either the user or the system bus. */
2013-06-27 19:28:09 +02:00
bool start_server ;
2009-04-06 02:31:22 +02:00
# endif
2006-01-10 17:51:06 +00:00
2008-08-29 21:43:50 +02:00
pa_log_set_ident ( " pulseaudio " ) ;
2009-04-10 03:41:25 +02:00
pa_log_set_level ( PA_LOG_NOTICE ) ;
2009-02-21 22:45:56 +01:00
pa_log_set_flags ( PA_LOG_COLORS | PA_LOG_PRINT_FILE | PA_LOG_PRINT_LEVEL , PA_LOG_RESET ) ;
2008-08-29 21:43:50 +02:00
2007-10-28 19:13:50 +00:00
# if defined(__linux__) && defined(__OPTIMIZE__)
/*
Disable lazy relocations to make usage of external libraries
more deterministic for our RT threads . We abuse __OPTIMIZE__ as
2009-07-20 15:47:57 +01:00
a check whether we are a debug build or not . This all is
admittedly a bit snake - oilish .
2007-10-28 19:13:50 +00:00
*/
if ( ! getenv ( " LD_BIND_NOW " ) ) {
2007-10-29 15:33:07 +00:00
char * rp ;
2009-09-26 20:18:00 +01:00
char * canonical_rp ;
2007-10-28 19:13:50 +00:00
/* We have to execute ourselves, because the libc caches the
* value of $ LD_BIND_NOW on initialization . */
2007-10-29 15:33:07 +00:00
2008-05-15 23:34:41 +00:00
pa_set_env ( " LD_BIND_NOW " , " 1 " ) ;
2009-02-18 21:45:06 +01:00
2009-10-30 09:54:08 -05:00
if ( ( canonical_rp = pa_realpath ( PA_BINARY ) ) ) {
2009-09-26 20:18:00 +01:00
2009-10-30 05:08:48 +01:00
if ( ( rp = pa_readlink ( " /proc/self/exe " ) ) ) {
2009-07-20 15:47:57 +01:00
2009-10-30 05:08:48 +01:00
if ( pa_streq ( rp , canonical_rp ) )
pa_assert_se ( execv ( rp , argv ) = = 0 ) ;
else
pa_log_warn ( " /proc/self/exe does not point to %s, cannot self execute. Are you playing games? " , canonical_rp ) ;
2009-07-20 15:47:57 +01:00
2009-10-30 05:08:48 +01:00
pa_xfree ( rp ) ;
2009-07-20 15:47:57 +01:00
2009-10-30 05:08:48 +01:00
} else
pa_log_warn ( " Couldn't read /proc/self/exe, cannot self execute. Running in a chroot()? " ) ;
pa_xfree ( canonical_rp ) ;
2009-09-26 20:18:00 +01:00
2009-10-30 05:08:48 +01:00
} else
pa_log_warn ( " Couldn't canonicalize binary path, cannot self execute. " ) ;
2007-10-28 19:13:50 +00:00
}
# endif
2014-10-16 10:05:19 +01:00
# ifdef HAVE_SYSTEMD_DAEMON
n_fds = sd_listen_fds ( 0 ) ;
if ( n_fds > 0 ) {
int i = n_fds ;
2008-05-15 23:34:41 +00:00
2014-10-16 10:05:19 +01:00
passed_fds = pa_xnew ( int , n_fds + 2 ) ;
passed_fds [ n_fds ] = passed_fds [ n_fds + 1 ] = - 1 ;
while ( i - - )
passed_fds [ i ] = SD_LISTEN_FDS_START + i ;
}
# endif
if ( ! passed_fds ) {
n_fds = 0 ;
passed_fds = pa_xnew ( int , 2 ) ;
passed_fds [ 0 ] = passed_fds [ 1 ] = - 1 ;
}
if ( ( e = getenv ( " PULSE_PASSED_FD " ) ) ) {
int passed_fd = atoi ( e ) ;
if ( passed_fd > 2 )
passed_fds [ n_fds ] = passed_fd ;
2008-05-15 23:34:41 +00:00
}
2009-06-19 17:37:18 +02:00
/* We might be autospawned, in which case have no idea in which
* context we have been started . Let ' s cleanup our execution
* context as good as possible */
2009-07-22 22:47:51 +02:00
2009-08-12 21:36:52 +02:00
pa_reset_personality ( ) ;
2009-06-19 17:37:18 +02:00
pa_drop_root ( ) ;
2014-10-16 10:05:19 +01:00
pa_close_allv ( passed_fds ) ;
pa_xfree ( passed_fds ) ;
2008-05-15 23:34:41 +00:00
pa_reset_sigs ( - 1 ) ;
pa_unblock_sigs ( - 1 ) ;
2009-08-12 21:37:40 +02:00
pa_reset_priority ( ) ;
2008-05-15 23:34:41 +00:00
2007-11-21 01:30:40 +00:00
setlocale ( LC_ALL , " " ) ;
2008-08-06 18:54:13 +02:00
pa_init_i18n ( ) ;
2004-09-17 20:06:17 +00:00
conf = pa_daemon_conf_new ( ) ;
2007-01-04 13:43:45 +00:00
2004-09-17 20:06:17 +00:00
if ( pa_daemon_conf_load ( conf , NULL ) < 0 )
2004-09-13 23:28:30 +00:00
goto finish ;
2004-12-11 00:10:41 +00:00
2004-09-17 20:06:17 +00:00
if ( pa_daemon_conf_env ( conf ) < 0 )
goto finish ;
2004-12-11 00:10:41 +00:00
2004-09-13 23:28:30 +00:00
if ( pa_cmdline_parse ( conf , argc , argv , & d ) < 0 ) {
2008-08-06 18:54:13 +02:00
pa_log ( _ ( " Failed to parse command line. " ) ) ;
2004-07-15 19:00:42 +00:00
goto finish ;
2004-07-12 21:28:11 +00:00
}
2004-12-11 00:10:41 +00:00
2013-06-19 11:59:08 +08:00
if ( conf - > log_target )
pa_log_set_target ( conf - > log_target ) ;
else {
pa_log_target target = { . type = PA_LOG_STDERR , . file = NULL } ;
pa_log_set_target ( & target ) ;
}
2009-02-21 22:45:56 +01:00
pa_log_set_level ( conf - > log_level ) ;
if ( conf - > log_meta )
pa_log_set_flags ( PA_LOG_PRINT_META , PA_LOG_SET ) ;
if ( conf - > log_time )
pa_log_set_flags ( PA_LOG_PRINT_TIME , PA_LOG_SET ) ;
2008-10-21 19:15:41 +02:00
pa_log_set_show_backtrace ( conf - > log_backtrace ) ;
2004-09-13 23:28:30 +00:00
2009-06-12 07:16:05 +03:00
# ifdef HAVE_DBUS
/* conf->system_instance and conf->local_server_type control almost the
* same thing ; make them agree about what is requested . */
switch ( conf - > local_server_type ) {
case PA_SERVER_TYPE_UNSET :
conf - > local_server_type = conf - > system_instance ? PA_SERVER_TYPE_SYSTEM : PA_SERVER_TYPE_USER ;
break ;
case PA_SERVER_TYPE_USER :
case PA_SERVER_TYPE_NONE :
2013-06-27 19:28:09 +02:00
conf - > system_instance = false ;
2009-06-12 07:16:05 +03:00
break ;
case PA_SERVER_TYPE_SYSTEM :
2013-06-27 19:28:09 +02:00
conf - > system_instance = true ;
2009-06-12 07:16:05 +03:00
break ;
default :
pa_assert_not_reached ( ) ;
}
2009-06-29 18:35:06 +03:00
start_server = conf - > local_server_type = = PA_SERVER_TYPE_USER | | ( getuid ( ) = = 0 & & conf - > local_server_type = = PA_SERVER_TYPE_SYSTEM ) ;
2009-06-12 07:16:05 +03:00
if ( ! start_server & & conf - > local_server_type = = PA_SERVER_TYPE_SYSTEM ) {
pa_log_notice ( _ ( " System mode refused for non-root user. Only starting the D-Bus server lookup service. " ) ) ;
2013-06-27 19:28:09 +02:00
conf - > system_instance = false ;
2009-06-12 07:16:05 +03:00
}
# endif
2007-11-21 01:30:40 +00:00
LTDL_SET_PRELOADED_SYMBOLS ( ) ;
pa_ltdl_init ( ) ;
2013-06-27 19:28:09 +02:00
ltdl_init = true ;
2007-11-21 01:30:40 +00:00
2004-09-13 23:28:30 +00:00
if ( conf - > dl_search_path )
lt_dlsetsearchpath ( conf - > dl_search_path ) ;
2007-11-21 01:30:40 +00:00
# ifdef OS_IS_WIN32
{
WSADATA data ;
WSAStartup ( MAKEWORD ( 2 , 0 ) , & data ) ;
}
# endif
pa_random_seed ( ) ;
2004-09-14 17:52:11 +00:00
switch ( conf - > cmd ) {
case PA_CMD_DUMP_MODULES :
pa_dump_modules ( conf , argc - d , argv + d ) ;
retval = 0 ;
goto finish ;
2004-09-05 00:03:16 +00:00
2004-09-14 17:52:11 +00:00
case PA_CMD_DUMP_CONF : {
2009-11-20 17:48:04 +01:00
if ( d < argc ) {
pa_log ( " Too many arguments. \n " ) ;
goto finish ;
}
2006-01-11 01:17:39 +00:00
s = pa_daemon_conf_dump ( conf ) ;
2004-09-14 17:52:11 +00:00
fputs ( s , stdout ) ;
pa_xfree ( s ) ;
retval = 0 ;
goto finish ;
}
2004-07-15 19:00:42 +00:00
2007-10-28 19:13:50 +00:00
case PA_CMD_DUMP_RESAMPLE_METHODS : {
int i ;
2009-11-20 17:48:04 +01:00
if ( d < argc ) {
pa_log ( " Too many arguments. \n " ) ;
goto finish ;
}
2007-10-28 19:13:50 +00:00
for ( i = 0 ; i < PA_RESAMPLER_MAX ; i + + )
if ( pa_resample_method_supported ( i ) )
printf ( " %s \n " , pa_resample_method_to_string ( i ) ) ;
2008-12-16 18:17:21 +01:00
retval = 0 ;
2007-10-28 19:13:50 +00:00
goto finish ;
}
2004-09-14 17:52:11 +00:00
case PA_CMD_HELP :
pa_cmdline_help ( argv [ 0 ] ) ;
retval = 0 ;
goto finish ;
2004-09-01 00:23:51 +00:00
2004-09-14 17:52:11 +00:00
case PA_CMD_VERSION :
2009-11-20 17:48:04 +01:00
if ( d < argc ) {
pa_log ( " Too many arguments. \n " ) ;
goto finish ;
}
2004-09-14 17:52:11 +00:00
printf ( PACKAGE_NAME " " PACKAGE_VERSION " \n " ) ;
retval = 0 ;
goto finish ;
2004-11-20 23:48:18 +00:00
case PA_CMD_CHECK : {
pid_t pid ;
2009-11-20 17:48:04 +01:00
if ( d < argc ) {
pa_log ( " Too many arguments. \n " ) ;
goto finish ;
}
2007-11-21 01:30:40 +00:00
if ( pa_pid_file_check_running ( & pid , " pulseaudio " ) < 0 )
2014-09-02 12:09:44 +02:00
pa_log_info ( " Daemon not running " ) ;
2007-11-21 01:30:40 +00:00
else {
2014-09-02 12:09:44 +02:00
pa_log_info ( " Daemon running as PID %u " , pid ) ;
2004-11-20 23:48:18 +00:00
retval = 0 ;
}
goto finish ;
}
case PA_CMD_KILL :
2009-11-20 17:48:04 +01:00
if ( d < argc ) {
pa_log ( " Too many arguments. \n " ) ;
goto finish ;
}
2007-11-21 01:30:40 +00:00
if ( pa_pid_file_kill ( SIGINT , NULL , " pulseaudio " ) < 0 )
2008-08-09 03:47:59 +02:00
pa_log ( _ ( " Failed to kill daemon: %s " ) , pa_cstrerror ( errno ) ) ;
2004-11-20 23:48:18 +00:00
else
retval = 0 ;
2007-01-04 13:43:45 +00:00
2004-11-20 23:48:18 +00:00
goto finish ;
2007-01-04 13:43:45 +00:00
2007-10-28 19:13:50 +00:00
case PA_CMD_CLEANUP_SHM :
2009-11-20 17:48:04 +01:00
if ( d < argc ) {
pa_log ( " Too many arguments. \n " ) ;
goto finish ;
}
2007-10-28 19:13:50 +00:00
if ( pa_shm_cleanup ( ) > = 0 )
retval = 0 ;
goto finish ;
2004-09-14 17:52:11 +00:00
default :
2008-06-11 17:38:50 +00:00
pa_assert ( conf - > cmd = = PA_CMD_DAEMON | | conf - > cmd = = PA_CMD_START ) ;
2004-09-14 17:52:11 +00:00
}
2004-09-01 00:23:51 +00:00
2009-11-20 17:48:04 +01:00
if ( d < argc ) {
pa_log ( " Too many arguments. \n " ) ;
goto finish ;
}
2011-01-06 00:51:33 +01:00
# ifdef HAVE_GETUID
2009-06-19 17:37:18 +02:00
if ( getuid ( ) = = 0 & & ! conf - > system_instance )
2008-08-06 18:54:13 +02:00
pa_log_warn ( _ ( " This program is not intended to be run as root (unless --system is specified). " ) ) ;
2009-06-12 07:16:05 +03:00
# ifndef HAVE_DBUS /* A similar, only a notice worthy check was done earlier, if D-Bus is enabled. */
2009-06-19 17:37:18 +02:00
else if ( getuid ( ) ! = 0 & & conf - > system_instance ) {
2008-10-19 22:25:58 +02:00
pa_log ( _ ( " Root privileges required. " ) ) ;
2006-07-19 17:44:19 +00:00
goto finish ;
}
2009-06-12 07:16:05 +03:00
# endif
2011-01-06 00:51:33 +01:00
# endif /* HAVE_GETUID */
2006-07-19 17:44:19 +00:00
2008-07-30 20:36:34 +02:00
if ( conf - > cmd = = PA_CMD_START & & conf - > system_instance ) {
2008-08-06 18:54:13 +02:00
pa_log ( _ ( " --start not supported for system instances. " ) ) ;
2008-07-30 20:36:34 +02:00
goto finish ;
}
2010-01-09 11:55:15 +02:00
if ( conf - > cmd = = PA_CMD_START & & ( configured_address = check_configured_address ( ) ) ) {
2011-03-25 23:03:31 +00:00
/* There is an server address in our config, but where did it come from?
* By default a standard X11 login will load module - x11 - publish which will
* inject PULSE_SERVER X11 property . If the PA daemon crashes , we will end
* up hitting this code path . So we have to check to see if our configured_address
* is the same as the value that would go into this property so that we can
* recover ( i . e . autospawn ) from a crash .
*/
char * ufn ;
2013-06-27 19:28:09 +02:00
bool start_anyway = false ;
2011-03-25 23:03:31 +00:00
if ( ( ufn = pa_runtime_path ( PA_NATIVE_DEFAULT_UNIX_SOCKET ) ) ) {
char * id ;
if ( ( id = pa_machine_id ( ) ) ) {
pa_strlist * server_list ;
char formatted_ufn [ 256 ] ;
pa_snprintf ( formatted_ufn , sizeof ( formatted_ufn ) , " {%s}unix:%s " , id , ufn ) ;
pa_xfree ( id ) ;
if ( ( server_list = pa_strlist_parse ( configured_address ) ) ) {
char * u = NULL ;
/* We only need to check the first server */
server_list = pa_strlist_pop ( server_list , & u ) ;
pa_strlist_free ( server_list ) ;
start_anyway = ( u & & pa_streq ( formatted_ufn , u ) ) ;
pa_xfree ( u ) ;
}
}
pa_xfree ( ufn ) ;
}
if ( ! start_anyway ) {
pa_log_notice ( _ ( " User-configured server at %s, refusing to start/autospawn. " ) , configured_address ) ;
pa_xfree ( configured_address ) ;
retval = 0 ;
goto finish ;
}
pa_log_notice ( _ ( " User-configured server at %s, which appears to be local. Probing deeper. " ) , configured_address ) ;
2010-01-09 11:55:15 +02:00
pa_xfree ( configured_address ) ;
}
2008-08-06 19:56:15 +02:00
if ( conf - > system_instance & & ! conf - > disallow_exit )
2015-06-15 17:34:07 +05:30
pa_log_warn ( _ ( " Running in system mode, but --disallow-exit not set. " ) ) ;
2008-08-06 19:56:15 +02:00
if ( conf - > system_instance & & ! conf - > disallow_module_loading )
2015-06-15 17:34:07 +05:30
pa_log_warn ( _ ( " Running in system mode, but --disallow-module-loading not set. " ) ) ;
2008-08-06 19:56:15 +02:00
if ( conf - > system_instance & & ! conf - > disable_shm ) {
2015-06-15 17:34:07 +05:30
pa_log_notice ( _ ( " Running in system mode, forcibly disabling SHM mode. " ) ) ;
2013-06-27 19:28:09 +02:00
conf - > disable_shm = true ;
2008-08-06 19:56:15 +02:00
}
2008-10-07 02:00:07 +02:00
if ( conf - > system_instance & & conf - > exit_idle_time > = 0 ) {
2015-06-15 17:34:07 +05:30
pa_log_notice ( _ ( " Running in system mode, forcibly disabling exit idle time. " ) ) ;
2008-10-07 02:00:07 +02:00
conf - > exit_idle_time = - 1 ;
2008-08-06 19:56:15 +02:00
}
2008-06-11 17:38:50 +00:00
if ( conf - > cmd = = PA_CMD_START ) {
/* If we shall start PA only when it is not running yet, we
* first take the autospawn lock to make things
* synchronous . */
2014-04-13 19:15:28 +02:00
/* This locking and thread synchronisation code doesn't work reliably
* on kFreeBSD ( Debian bug # 705435 ) , or in upstream FreeBSD ports
* ( bug reference : ports / 128947 , patched in SVN r231972 ) . */
# if !defined(__FreeBSD__) && !defined(__FreeBSD_kernel__)
2008-08-09 03:49:42 +02:00
if ( ( autospawn_fd = pa_autospawn_lock_init ( ) ) < 0 ) {
pa_log ( " Failed to initialize autospawn lock " ) ;
goto finish ;
}
2013-06-27 19:28:09 +02:00
if ( ( pa_autospawn_lock_acquire ( true ) < 0 ) ) {
2008-08-09 03:49:42 +02:00
pa_log ( " Failed to acquire autospawn lock " ) ;
goto finish ;
}
2013-06-27 19:28:09 +02:00
autospawn_locked = true ;
2014-04-13 19:15:28 +02:00
# endif
2008-06-11 17:38:50 +00:00
}
2004-09-13 23:28:30 +00:00
if ( conf - > daemonize ) {
2011-06-23 22:21:03 +02:00
# ifdef HAVE_FORK
2004-07-15 19:00:42 +00:00
pid_t child ;
2011-06-23 22:21:03 +02:00
# endif
2004-07-15 19:00:42 +00:00
if ( pa_stdio_acquire ( ) < 0 ) {
2008-08-06 18:54:13 +02:00
pa_log ( _ ( " Failed to acquire stdio. " ) ) ;
2004-07-15 19:00:42 +00:00
goto finish ;
}
2006-01-10 17:51:06 +00:00
# ifdef HAVE_FORK
2004-07-15 19:00:42 +00:00
if ( pipe ( daemon_pipe ) < 0 ) {
2009-10-31 02:43:47 +01:00
pa_log ( _ ( " pipe() failed: %s " ) , pa_cstrerror ( errno ) ) ;
2004-07-15 19:00:42 +00:00
goto finish ;
}
2007-01-04 13:43:45 +00:00
2004-07-15 19:00:42 +00:00
if ( ( child = fork ( ) ) < 0 ) {
2008-08-06 18:54:13 +02:00
pa_log ( _ ( " fork() failed: %s " ) , pa_cstrerror ( errno ) ) ;
2011-03-25 09:12:51 +00:00
pa_close_pipe ( daemon_pipe ) ;
2004-07-15 19:00:42 +00:00
goto finish ;
}
if ( child ! = 0 ) {
2008-05-15 23:34:41 +00:00
ssize_t n ;
2004-07-15 19:00:42 +00:00
/* Father */
2007-10-28 19:13:50 +00:00
pa_assert_se ( pa_close ( daemon_pipe [ 1 ] ) = = 0 ) ;
2004-07-15 19:00:42 +00:00
daemon_pipe [ 1 ] = - 1 ;
2008-05-15 23:34:41 +00:00
if ( ( n = pa_loop_read ( daemon_pipe [ 0 ] , & retval , sizeof ( retval ) , NULL ) ) ! = sizeof ( retval ) ) {
if ( n < 0 )
2008-08-06 18:54:13 +02:00
pa_log ( _ ( " read() failed: %s " ) , pa_cstrerror ( errno ) ) ;
2008-05-15 23:34:41 +00:00
2004-07-15 19:00:42 +00:00
retval = 1 ;
}
2004-12-11 00:10:41 +00:00
if ( retval )
2008-08-06 18:54:13 +02:00
pa_log ( _ ( " Daemon startup failed. " ) ) ;
2004-12-11 00:10:41 +00:00
else
2014-09-02 12:09:44 +02:00
pa_log_info ( " Daemon startup successful. " ) ;
2007-01-04 13:43:45 +00:00
2004-07-15 19:00:42 +00:00
goto finish ;
}
2008-08-09 03:49:42 +02:00
if ( autospawn_fd > = 0 ) {
2008-06-11 17:38:50 +00:00
/* The lock file is unlocked from the parent, so we need
* to close it in the child */
2008-08-09 03:49:42 +02:00
pa_autospawn_lock_release ( ) ;
2013-06-27 19:28:09 +02:00
pa_autospawn_lock_done ( true ) ;
2008-08-09 03:49:42 +02:00
2013-06-27 19:28:09 +02:00
autospawn_locked = false ;
2008-08-09 03:49:42 +02:00
autospawn_fd = - 1 ;
2008-06-11 17:38:50 +00:00
}
2007-10-28 19:13:50 +00:00
pa_assert_se ( pa_close ( daemon_pipe [ 0 ] ) = = 0 ) ;
2004-07-15 19:00:42 +00:00
daemon_pipe [ 0 ] = - 1 ;
2006-01-10 17:51:06 +00:00
# endif
2004-09-05 00:03:16 +00:00
2013-06-19 11:59:08 +08:00
if ( ! conf - > log_target ) {
2014-10-17 13:32:03 +02:00
# ifdef HAVE_SYSTEMD_JOURNAL
2013-12-03 01:09:56 +01:00
pa_log_target target = { . type = PA_LOG_JOURNAL , . file = NULL } ;
# else
2013-06-19 11:59:08 +08:00
pa_log_target target = { . type = PA_LOG_SYSLOG , . file = NULL } ;
2013-12-03 01:09:56 +01:00
# endif
2013-06-19 11:59:08 +08:00
pa_log_set_target ( & target ) ;
}
2004-09-05 00:03:16 +00:00
2006-01-10 17:51:06 +00:00
# ifdef HAVE_SETSID
2009-10-31 02:43:47 +01:00
if ( setsid ( ) < 0 ) {
pa_log ( _ ( " setsid() failed: %s " ) , pa_cstrerror ( errno ) ) ;
goto finish ;
}
2006-01-10 17:51:06 +00:00
# endif
2011-03-24 21:27:55 +00:00
# ifdef HAVE_FORK
2009-10-31 02:43:47 +01:00
/* We now are a session and process group leader. Let's fork
* again and let the father die , so that we ' ll become a
* process that can never acquire a TTY again , in a session and
* process group without leader */
2004-12-14 14:09:00 +00:00
2011-03-24 21:27:55 +00:00
if ( pipe ( daemon_pipe2 ) < 0 ) {
pa_log ( _ ( " pipe() failed: %s " ) , pa_cstrerror ( errno ) ) ;
goto finish ;
}
2009-10-31 02:43:47 +01:00
if ( ( child = fork ( ) ) < 0 ) {
pa_log ( _ ( " fork() failed: %s " ) , pa_cstrerror ( errno ) ) ;
2011-03-25 09:12:51 +00:00
pa_close_pipe ( daemon_pipe2 ) ;
2009-10-31 02:43:47 +01:00
goto finish ;
}
if ( child ! = 0 ) {
2011-03-24 21:27:55 +00:00
ssize_t n ;
/* Father */
pa_assert_se ( pa_close ( daemon_pipe2 [ 1 ] ) = = 0 ) ;
daemon_pipe2 [ 1 ] = - 1 ;
if ( ( n = pa_loop_read ( daemon_pipe2 [ 0 ] , & retval , sizeof ( retval ) , NULL ) ) ! = sizeof ( retval ) ) {
if ( n < 0 )
pa_log ( _ ( " read() failed: %s " ) , pa_cstrerror ( errno ) ) ;
retval = 1 ;
}
/* We now have to take care of signalling the first fork with
* the return value we ' ve received from this fork . . . */
pa_assert ( daemon_pipe [ 1 ] > = 0 ) ;
pa_loop_write ( daemon_pipe [ 1 ] , & retval , sizeof ( retval ) , NULL ) ;
pa_close ( daemon_pipe [ 1 ] ) ;
daemon_pipe [ 1 ] = - 1 ;
2009-10-31 02:43:47 +01:00
goto finish ;
}
2011-03-24 21:27:55 +00:00
pa_assert_se ( pa_close ( daemon_pipe2 [ 0 ] ) = = 0 ) ;
daemon_pipe2 [ 0 ] = - 1 ;
/* We no longer need the (first) daemon_pipe as it's handled in our child above */
pa_close_pipe ( daemon_pipe ) ;
2006-01-10 17:51:06 +00:00
# endif
# ifdef SIGTTOU
2004-12-14 14:20:52 +00:00
signal ( SIGTTOU , SIG_IGN ) ;
2006-01-10 17:51:06 +00:00
# endif
# ifdef SIGTTIN
2004-12-14 14:20:52 +00:00
signal ( SIGTTIN , SIG_IGN ) ;
2006-01-10 17:51:06 +00:00
# endif
# ifdef SIGTSTP
2004-12-14 14:20:52 +00:00
signal ( SIGTSTP , SIG_IGN ) ;
2006-01-10 17:51:06 +00:00
# endif
2007-01-04 13:43:45 +00:00
2009-10-31 02:43:47 +01:00
pa_nullify_stdfds ( ) ;
2004-07-12 21:28:11 +00:00
}
2004-07-17 15:00:31 +00:00
2009-09-02 00:42:54 +02:00
pa_set_env_and_record ( " PULSE_INTERNAL " , " 1 " ) ;
2007-10-28 19:13:50 +00:00
pa_assert_se ( chdir ( " / " ) = = 0 ) ;
2006-07-19 17:44:19 +00:00
umask ( 0022 ) ;
2007-01-04 13:43:45 +00:00
2009-06-19 17:37:18 +02:00
# ifdef HAVE_SYS_RESOURCE_H
set_all_rlimits ( conf ) ;
# endif
pa_rtclock_hrtimer_enable ( ) ;
2013-11-01 14:50:51 +01:00
if ( conf - > high_priority )
pa_raise_priority ( conf - > nice_level ) ;
2009-06-19 17:37:18 +02:00
2008-05-15 23:34:41 +00:00
if ( conf - > system_instance )
2006-07-19 17:44:19 +00:00
if ( change_user ( ) < 0 )
goto finish ;
2008-05-15 23:34:41 +00:00
2009-09-02 00:42:54 +02:00
pa_set_env_and_record ( " PULSE_SYSTEM " , conf - > system_instance ? " 1 " : " 0 " ) ;
2008-05-21 22:50:58 +00:00
2014-09-02 12:09:44 +02:00
pa_log_info ( " This is PulseAudio %s " , PACKAGE_VERSION ) ;
pa_log_debug ( " Compilation host: %s " , CANONICAL_HOST ) ;
pa_log_debug ( " Compilation CFLAGS: %s " , PA_CFLAGS ) ;
2008-09-01 02:38:32 +02:00
2014-11-11 15:39:59 +01:00
# ifdef HAVE_LIBSAMPLERATE
pa_log_warn ( " Compiled with DEPRECATED libsamplerate support! " ) ;
# endif
2008-09-05 15:42:39 +03:00
s = pa_uname_string ( ) ;
2014-09-02 12:09:44 +02:00
pa_log_debug ( " Running on host: %s " , s ) ;
2008-09-05 15:42:39 +03:00
pa_xfree ( s ) ;
2014-09-02 12:09:44 +02:00
pa_log_debug ( " Found %u CPUs. " , pa_ncpus ( ) ) ;
2009-01-22 02:16:53 +01:00
2014-09-02 12:09:44 +02:00
pa_log_info ( " Page size is %lu bytes " , ( unsigned long ) PA_PAGE_SIZE ) ;
2008-09-05 15:42:39 +03:00
2008-09-01 02:38:32 +02:00
# ifdef HAVE_VALGRIND_MEMCHECK_H
2014-09-02 12:09:44 +02:00
pa_log_debug ( " Compiled with Valgrind support: yes " ) ;
2008-09-01 02:38:32 +02:00
# else
2014-09-02 12:09:44 +02:00
pa_log_debug ( " Compiled with Valgrind support: no " ) ;
2008-09-01 02:38:32 +02:00
# endif
2014-09-02 12:09:44 +02:00
pa_log_debug ( " Running in valgrind mode: %s " , pa_yes_no ( pa_in_valgrind ( ) ) ) ;
2008-10-04 00:13:29 +02:00
2014-09-02 12:09:44 +02:00
pa_log_debug ( " Running in VM: %s " , pa_yes_no ( pa_running_in_vm ( ) ) ) ;
2009-11-05 03:22:48 +01:00
2008-09-01 02:38:32 +02:00
# ifdef __OPTIMIZE__
2014-09-02 12:09:44 +02:00
pa_log_debug ( " Optimized build: yes " ) ;
2008-09-01 02:38:32 +02:00
# else
2014-09-02 12:09:44 +02:00
pa_log_debug ( " Optimized build: no " ) ;
2008-09-01 02:38:32 +02:00
# endif
2009-03-20 13:29:42 +01:00
# ifdef NDEBUG
2014-09-02 12:09:44 +02:00
pa_log_debug ( " NDEBUG defined, all asserts disabled. " ) ;
2009-03-20 13:29:42 +01:00
# elif defined(FASTPATH)
2014-09-02 12:09:44 +02:00
pa_log_debug ( " FASTPATH defined, only fast path asserts disabled. " ) ;
2009-03-20 13:29:42 +01:00
# else
2014-09-02 12:09:44 +02:00
pa_log_debug ( " All asserts enabled. " ) ;
2009-03-20 13:29:42 +01:00
# endif
2008-08-07 02:23:45 +02:00
if ( ! ( s = pa_machine_id ( ) ) ) {
pa_log ( _ ( " Failed to get machine ID " ) ) ;
goto finish ;
}
2014-09-02 12:09:44 +02:00
pa_log_info ( " Machine ID is %s. " , s ) ;
2008-08-07 02:23:45 +02:00
pa_xfree ( s ) ;
2009-04-13 22:21:26 +02:00
if ( ( s = pa_session_id ( ) ) ) {
2014-09-02 12:09:44 +02:00
pa_log_info ( " Session ID is %s. " , s ) ;
2009-06-19 17:37:18 +02:00
pa_xfree ( s ) ;
2009-04-13 22:21:26 +02:00
}
2008-05-21 22:50:58 +00:00
if ( ! ( s = pa_get_runtime_dir ( ) ) )
goto finish ;
2014-09-02 12:09:44 +02:00
pa_log_info ( " Using runtime directory %s. " , s ) ;
2008-05-15 23:34:41 +00:00
pa_xfree ( s ) ;
2008-08-07 02:23:45 +02:00
2008-05-21 22:50:58 +00:00
if ( ! ( s = pa_get_state_dir ( ) ) )
2008-08-07 02:23:45 +02:00
goto finish ;
2014-09-02 12:09:44 +02:00
pa_log_info ( " Using state directory %s. " , s ) ;
2008-05-21 22:50:58 +00:00
pa_xfree ( s ) ;
2014-09-02 12:09:44 +02:00
pa_log_info ( " Using modules directory %s. " , conf - > dl_search_path ) ;
2009-08-21 03:43:53 +02:00
2014-09-02 12:09:44 +02:00
pa_log_info ( " Running in system mode: %s " , pa_yes_no ( pa_in_system_mode ( ) ) ) ;
2007-01-04 13:43:45 +00:00
2009-06-17 03:00:51 +02:00
if ( pa_in_system_mode ( ) )
2016-07-14 11:38:35 +09:00
pa_log_warn ( _ ( " OK, so you are running PA in system mode. Please make sure that you actually do want to do that. \n "
2014-11-29 21:09:30 +05:00
" Please read http://www.freedesktop.org/wiki/Software/PulseAudio/Documentation/User/WhatIsWrongWithSystemWide/ for an explanation why system mode is usually a bad idea. " ) ) ;
2009-06-17 03:00:51 +02:00
2004-11-20 23:48:18 +00:00
if ( conf - > use_pid_file ) {
2008-06-11 17:38:50 +00:00
int z ;
if ( ( z = pa_pid_file_create ( " pulseaudio " ) ) ! = 0 ) {
if ( conf - > cmd = = PA_CMD_START & & z > 0 ) {
/* If we are already running and with are run in
* - - start mode , then let ' s return this as success . */
retval = 0 ;
goto finish ;
}
2008-08-06 18:54:13 +02:00
pa_log ( _ ( " pa_pid_file_create() failed. " ) ) ;
2004-11-20 23:48:18 +00:00
goto finish ;
2004-12-15 01:17:04 +00:00
}
2004-11-20 23:48:18 +00:00
2013-06-27 19:28:09 +02:00
valid_pid_file = true ;
2004-11-20 23:48:18 +00:00
}
2009-05-25 23:56:38 +02:00
pa_disable_sigpipe ( ) ;
2006-07-19 17:44:19 +00:00
2007-10-28 19:13:50 +00:00
if ( pa_rtclock_hrtimer ( ) )
2015-12-21 10:54:58 +05:30
pa_log_info ( " System supports high resolution timers " ) ;
2007-10-28 19:13:50 +00:00
else
2015-12-21 10:54:58 +05:30
pa_log_info ( " System appears to not support high resolution timers " ) ;
2007-10-28 19:13:50 +00:00
2009-06-07 00:43:03 +02:00
if ( conf - > lock_memory ) {
2013-09-18 16:22:00 +02:00
# if defined(HAVE_SYS_MMAN_H) && !defined(__ANDROID__)
2009-06-07 00:43:03 +02:00
if ( mlockall ( MCL_FUTURE ) < 0 )
pa_log_warn ( " mlockall() failed: %s " , pa_cstrerror ( errno ) ) ;
else
2010-12-20 17:20:57 +08:00
pa_log_info ( " Successfully locked process into memory. " ) ;
2009-06-07 00:43:03 +02:00
# else
pa_log_warn ( " Memory locking requested but not supported on platform. " ) ;
2007-10-28 19:13:50 +00:00
# endif
2009-06-07 00:43:03 +02:00
}
2007-10-28 19:13:50 +00:00
2009-04-21 22:56:08 +02:00
pa_memtrap_install ( ) ;
2007-10-28 19:13:50 +00:00
pa_assert_se ( mainloop = pa_mainloop_new ( ) ) ;
2004-06-08 23:54:24 +00:00
2016-04-15 23:07:36 +02:00
if ( ! ( c = pa_core_new ( pa_mainloop_get_api ( mainloop ) , ! conf - > disable_shm ,
! conf - > disable_shm & & ! conf - > disable_memfd & & pa_memfd_is_locally_supported ( ) ,
conf - > shm_size ) ) ) {
2008-08-06 18:54:13 +02:00
pa_log ( _ ( " pa_core_new() failed. " ) ) ;
2006-08-19 01:20:13 +00:00
goto finish ;
2006-08-22 12:46:05 +00:00
}
2006-08-19 01:20:13 +00:00
2007-10-28 19:13:50 +00:00
c - > default_sample_spec = conf - > default_sample_spec ;
2011-08-02 18:37:27 -05:00
c - > alternate_sample_rate = conf - > alternate_sample_rate ;
2009-02-21 16:32:42 +01:00
c - > default_channel_map = conf - > default_channel_map ;
2007-10-28 19:13:50 +00:00
c - > default_n_fragments = conf - > default_n_fragments ;
c - > default_fragment_size_msec = conf - > default_fragment_size_msec ;
2011-09-13 21:15:49 +01:00
c - > deferred_volume_safety_margin_usec = conf - > deferred_volume_safety_margin_usec ;
c - > deferred_volume_extra_delay_usec = conf - > deferred_volume_extra_delay_usec ;
2015-03-24 10:29:16 +01:00
c - > lfe_crossover_freq = conf - > lfe_crossover_freq ;
2007-10-28 19:13:50 +00:00
c - > exit_idle_time = conf - > exit_idle_time ;
c - > scache_idle_time = conf - > scache_idle_time ;
c - > resample_method = conf - > resample_method ;
2007-11-01 02:58:26 +00:00
c - > realtime_priority = conf - > realtime_priority ;
2014-10-23 15:00:29 +02:00
c - > realtime_scheduling = conf - > realtime_scheduling ;
c - > disable_remixing = conf - > disable_remixing ;
c - > disable_lfe_remixing = conf - > disable_lfe_remixing ;
c - > deferred_volume = conf - > deferred_volume ;
c - > running_as_daemon = conf - > daemonize ;
2008-08-06 19:39:12 +02:00
c - > disallow_exit = conf - > disallow_exit ;
2009-01-27 04:39:07 +01:00
c - > flat_volumes = conf - > flat_volumes ;
2009-06-29 18:35:06 +03:00
# ifdef HAVE_DBUS
2009-06-16 19:03:22 +03:00
c - > server_type = conf - > local_server_type ;
2009-06-29 18:35:06 +03:00
# endif
2007-10-28 19:13:50 +00:00
2014-09-10 15:23:11 +02:00
pa_cpu_init ( & c - > cpu_info ) ;
2010-09-14 15:21:49 +05:30
2007-10-28 19:13:50 +00:00
pa_assert_se ( pa_signal_init ( pa_mainloop_get_api ( mainloop ) ) = = 0 ) ;
2004-09-03 20:14:23 +00:00
pa_signal_new ( SIGINT , signal_callback , c ) ;
pa_signal_new ( SIGTERM , signal_callback , c ) ;
2006-01-10 17:51:06 +00:00
# ifdef SIGUSR1
2004-09-03 20:14:23 +00:00
pa_signal_new ( SIGUSR1 , signal_callback , c ) ;
2006-01-10 17:51:06 +00:00
# endif
# ifdef SIGUSR2
2004-09-03 20:14:23 +00:00
pa_signal_new ( SIGUSR2 , signal_callback , c ) ;
2006-01-10 17:51:06 +00:00
# endif
# ifdef SIGHUP
2004-09-26 17:02:26 +00:00
pa_signal_new ( SIGHUP , signal_callback , c ) ;
2006-01-10 17:51:06 +00:00
# endif
2007-01-04 13:43:45 +00:00
2007-10-28 19:13:50 +00:00
if ( ! conf - > no_cpu_limit )
pa_assert_se ( pa_cpu_limit_init ( pa_mainloop_get_api ( mainloop ) ) = = 0 ) ;
2007-01-04 13:43:45 +00:00
2004-07-14 21:52:41 +00:00
buf = pa_strbuf_new ( ) ;
2008-05-15 23:34:41 +00:00
2009-06-12 07:16:05 +03:00
# ifdef HAVE_DBUS
2012-03-13 00:06:22 +01:00
pa_assert_se ( dbus_threads_init_default ( ) ) ;
2009-06-12 07:16:05 +03:00
if ( start_server ) {
# endif
if ( conf - > load_default_script_file ) {
FILE * f ;
if ( ( f = pa_daemon_conf_open_default_script_file ( conf ) ) ) {
r = pa_cli_command_execute_file_stream ( c , f , buf , & conf - > fail ) ;
fclose ( f ) ;
}
2008-05-15 23:34:41 +00:00
}
2004-09-14 23:08:39 +00:00
2009-06-12 07:16:05 +03:00
if ( r > = 0 )
r = pa_cli_command_execute ( c , conf - > script_commands , buf , & conf - > fail ) ;
2008-05-15 23:34:41 +00:00
2015-06-12 18:17:07 +05:30
pa_log_error ( " %s " , s = pa_strbuf_to_string_free ( buf ) ) ;
2009-06-12 07:16:05 +03:00
pa_xfree ( s ) ;
2007-01-04 13:43:45 +00:00
2009-06-12 07:16:05 +03:00
if ( r < 0 & & conf - > fail ) {
pa_log ( _ ( " Failed to initialize daemon. " ) ) ;
goto finish ;
}
2007-11-01 11:23:45 +00:00
2009-06-12 07:16:05 +03:00
if ( ! c - > modules | | pa_idxset_size ( c - > modules ) = = 0 ) {
pa_log ( _ ( " Daemon startup without any loaded modules, refusing to work. " ) ) ;
goto finish ;
}
# ifdef HAVE_DBUS
} else {
/* When we just provide the D-Bus server lookup service, we don't want
* any modules to be loaded . We haven ' t loaded any so far , so one might
* think there ' s no way to contact the server , but receiving certain
* signals could still cause modules to load . */
2013-06-27 19:28:09 +02:00
conf - > disallow_module_loading = true ;
2008-05-15 23:34:41 +00:00
}
2009-06-12 07:16:05 +03:00
# endif
2004-11-20 23:48:18 +00:00
2009-06-12 07:16:05 +03:00
/* We completed the initial module loading, so let's disable it
* from now on , if requested */
2014-10-23 15:00:29 +02:00
c - > disallow_module_loading = conf - > disallow_module_loading ;
2008-05-15 23:34:41 +00:00
2009-03-20 18:39:30 +02:00
# ifdef HAVE_DBUS
2009-06-12 07:16:05 +03:00
if ( ! conf - > system_instance ) {
2011-10-06 23:28:37 +03:00
if ( ( server_lookup = pa_dbusobj_server_lookup_new ( c ) ) ) {
if ( ! ( lookup_service_bus = register_dbus_name ( c , DBUS_BUS_SESSION , " org.PulseAudio1 " ) ) )
goto finish ;
}
2009-06-12 07:16:05 +03:00
}
2011-10-06 23:28:37 +03:00
if ( start_server )
server_bus = register_dbus_name ( c , conf - > system_instance ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION , " org.pulseaudio.Server " ) ;
2009-03-20 18:39:30 +02:00
# endif
2010-01-14 02:33:49 +01:00
# ifdef HAVE_FORK
2011-03-24 21:27:55 +00:00
if ( daemon_pipe2 [ 1 ] > = 0 ) {
2010-01-14 02:33:49 +01:00
int ok = 0 ;
2011-03-24 21:27:55 +00:00
pa_loop_write ( daemon_pipe2 [ 1 ] , & ok , sizeof ( ok ) , NULL ) ;
pa_close ( daemon_pipe2 [ 1 ] ) ;
daemon_pipe2 [ 1 ] = - 1 ;
2010-01-14 02:33:49 +01:00
}
# endif
2014-09-02 12:09:44 +02:00
pa_log_info ( " Daemon startup complete. " ) ;
2008-05-15 23:34:41 +00:00
2015-08-13 19:58:27 -03:00
# ifdef HAVE_SYSTEMD_DAEMON
sd_notify ( 0 , " READY=1 " ) ;
# endif
2008-05-15 23:34:41 +00:00
retval = 0 ;
if ( pa_mainloop_run ( mainloop , & retval ) < 0 )
goto finish ;
2014-09-02 12:09:44 +02:00
pa_log_info ( " Daemon shutdown initiated. " ) ;
2008-05-15 23:34:41 +00:00
2015-08-13 19:58:27 -03:00
# ifdef HAVE_SYSTEMD_DAEMON
sd_notify ( 0 , " STOPPING=1 " ) ;
# endif
2008-05-15 23:34:41 +00:00
finish :
2009-04-06 02:31:22 +02:00
# ifdef HAVE_DBUS
2009-06-12 07:16:05 +03:00
if ( server_bus )
pa_dbus_connection_unref ( server_bus ) ;
if ( lookup_service_bus )
pa_dbus_connection_unref ( lookup_service_bus ) ;
if ( server_lookup )
pa_dbusobj_server_lookup_free ( server_lookup ) ;
2009-04-06 02:31:22 +02:00
# endif
2006-01-10 17:51:06 +00:00
2008-08-09 03:49:42 +02:00
if ( autospawn_fd > = 0 ) {
if ( autospawn_locked )
pa_autospawn_lock_release ( ) ;
2013-06-27 19:28:09 +02:00
pa_autospawn_lock_done ( false ) ;
2008-08-09 03:49:42 +02:00
}
2008-06-11 17:38:50 +00:00
2008-05-15 23:34:41 +00:00
if ( c ) {
2011-08-16 10:54:24 +01:00
/* Ensure all the modules/samples are unloaded when the core is still ref'ed,
* as unlink callback hooks in modules may need the core to be ref ' ed */
pa_module_unload_all ( c ) ;
pa_scache_free_all ( c ) ;
2008-05-15 23:34:41 +00:00
pa_core_unref ( c ) ;
2014-09-02 12:09:44 +02:00
pa_log_info ( " Daemon terminated. " ) ;
2008-05-15 23:34:41 +00:00
}
2004-06-23 23:17:30 +00:00
2006-07-25 20:51:15 +00:00
if ( ! conf - > no_cpu_limit )
pa_cpu_limit_done ( ) ;
2007-01-04 13:43:45 +00:00
2004-06-23 23:17:30 +00:00
pa_signal_done ( ) ;
2007-01-04 13:43:45 +00:00
2008-05-15 23:34:41 +00:00
# ifdef HAVE_FORK
2011-03-25 09:12:51 +00:00
/* If we have daemon_pipe[1] still open, this means we've failed after
* the first fork , but before the second . Therefore just write to it . */
if ( daemon_pipe [ 1 ] > = 0 )
pa_loop_write ( daemon_pipe [ 1 ] , & retval , sizeof ( retval ) , NULL ) ;
else if ( daemon_pipe2 [ 1 ] > = 0 )
2011-03-24 21:27:55 +00:00
pa_loop_write ( daemon_pipe2 [ 1 ] , & retval , sizeof ( retval ) , NULL ) ;
2008-06-11 17:38:50 +00:00
2011-03-24 21:27:55 +00:00
pa_close_pipe ( daemon_pipe2 ) ;
2011-03-25 09:12:51 +00:00
pa_close_pipe ( daemon_pipe ) ;
2008-05-15 23:34:41 +00:00
# endif
2004-07-15 19:00:42 +00:00
2006-08-19 01:20:13 +00:00
if ( mainloop )
pa_mainloop_free ( mainloop ) ;
2004-09-13 23:28:30 +00:00
if ( conf )
2004-09-17 20:06:17 +00:00
pa_daemon_conf_free ( conf ) ;
2004-07-15 19:00:42 +00:00
2004-11-20 23:48:18 +00:00
if ( valid_pid_file )
pa_pid_file_remove ( ) ;
2007-01-04 13:43:45 +00:00
2009-09-02 00:42:54 +02:00
/* This has no real purpose except making things valgrind-clean */
pa_unset_env_recorded ( ) ;
2006-01-10 17:51:06 +00:00
# ifdef OS_IS_WIN32
WSACleanup ( ) ;
# endif
2008-02-15 18:03:11 +00:00
if ( ltdl_init )
pa_ltdl_done ( ) ;
2007-10-28 19:13:50 +00:00
# ifdef HAVE_DBUS
dbus_shutdown ( ) ;
# endif
2007-01-04 13:43:45 +00:00
2004-06-23 23:17:30 +00:00
return retval ;
2004-06-08 23:54:24 +00:00
}