From 12c5c62dadad248f4a01a9973b6e99c99d0badad Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 5 Sep 2008 00:38:52 +0200 Subject: Downgrade hrtimer warning to notice level --- src/modules/module-alsa-sink.c | 2 +- src/modules/module-alsa-source.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c index e3f9a5ff..6f0d7830 100644 --- a/src/modules/module-alsa-sink.c +++ b/src/modules/module-alsa-sink.c @@ -1241,7 +1241,7 @@ int pa__init(pa_module*m) { } if (use_tsched && !pa_rtclock_hrtimer()) { - pa_log("Disabling timer-based scheduling because high-resolution timers are not available from the kernel."); + pa_log_notice("Disabling timer-based scheduling because high-resolution timers are not available from the kernel."); use_tsched = FALSE; } diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c index 54ffde57..fca05006 100644 --- a/src/modules/module-alsa-source.c +++ b/src/modules/module-alsa-source.c @@ -1073,7 +1073,7 @@ int pa__init(pa_module*m) { } if (use_tsched && !pa_rtclock_hrtimer()) { - pa_log("Disabling timer-based scheduling because high-resolution timers are not available from the kernel."); + pa_log_notice("Disabling timer-based scheduling because high-resolution timers are not available from the kernel."); use_tsched = FALSE; } -- cgit From 456284918ab04cde6c661839d706cb84baf3a887 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 5 Sep 2008 00:39:36 +0200 Subject: update documentation and help texts for s32le/s32be sample types --- src/utils/pacat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/utils/pacat.c b/src/utils/pacat.c index c1826d7b..f42abc8e 100644 --- a/src/utils/pacat.c +++ b/src/utils/pacat.c @@ -500,7 +500,7 @@ static void help(const char *argv0) { " --volume=VOLUME Specify the initial (linear) volume in range 0...65536\n" " --rate=SAMPLERATE The sample rate in Hz (defaults to 44100)\n" " --format=SAMPLEFORMAT The sample type, one of s16le, s16be, u8, float32le,\n" - " float32be, ulaw, alaw (defaults to s16ne)\n" + " float32be, ulaw, alaw, s32le, s32be (defaults to s16ne)\n" " --channels=CHANNELS The number of channels, 1 for mono, 2 for stereo\n" " (defaults to 2)\n" " --channel-map=CHANNELMAP Channel map to use instead of the default\n" -- cgit From 5a9a6021f12ebfcdc071d07488723ab8c0adfd5f Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 5 Sep 2008 01:28:08 +0200 Subject: update map-file script to ignore gcc malloc attributes --- src/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/Makefile.am b/src/Makefile.am index a20c7c45..3ee53722 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1625,7 +1625,7 @@ update-ffmpeg: update-map-file: ( echo "PULSE_0 {" ; \ echo "global:" ; \ - ctags -I PA_GCC_PURE,PA_GCC_CONST,PA_GCC_DEPRECATED,PA_GCC_PRINTF_ATTR -f - --c-kinds=p $(pulseinclude_HEADERS) | awk '/^pa_/ { print $$1 ";" }' | sort ; \ + ctags -I PA_GCC_MALLOC,PA_GCC_ALLOC_SIZE2,PA_GCC_ALLOC_SIZE,PA_GCC_PURE,PA_GCC_CONST,PA_GCC_DEPRECATED,PA_GCC_PRINTF_ATTR -f - --c-kinds=p $(pulseinclude_HEADERS) | awk '/^pa_/ { print $$1 ";" }' | sort ; \ echo "local:" ; \ echo "*;" ; \ echo "};" ) > $(srcdir)/map-file -- cgit From cb0c97dae7655eda60cabc06df0d1da4666392ec Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 5 Sep 2008 01:29:07 +0200 Subject: add new API function pa_channel_map_compatible() --- src/pulse/channelmap.c | 7 +++++++ src/pulse/channelmap.h | 4 ++++ 2 files changed, 11 insertions(+) (limited to 'src') diff --git a/src/pulse/channelmap.c b/src/pulse/channelmap.c index 1766e729..7a21998e 100644 --- a/src/pulse/channelmap.c +++ b/src/pulse/channelmap.c @@ -560,3 +560,10 @@ int pa_channel_map_valid(const pa_channel_map *map) { return 1; } + +int pa_channel_map_compatible(const pa_channel_map *map, const pa_sample_spec *ss) { + pa_assert(map); + pa_assert(ss); + + return map->channels == ss->channels; +} diff --git a/src/pulse/channelmap.h b/src/pulse/channelmap.h index f9086d19..035f9b1a 100644 --- a/src/pulse/channelmap.h +++ b/src/pulse/channelmap.h @@ -214,6 +214,10 @@ int pa_channel_map_equal(const pa_channel_map *a, const pa_channel_map *b) PA_GC /** Return non-zero of the specified channel map is considered valid */ int pa_channel_map_valid(const pa_channel_map *map) PA_GCC_PURE; +/** Return non-zero if the specified channel map is compatible with + * the specified sample spec. \since 0.9.12 */ +int pa_channel_map_compatible(const pa_channel_map *map, const pa_sample_spec *ss) PA_GCC_PURE; + PA_C_DECL_END #endif -- cgit From ece297f21b627dfb71e853a57dcacbd1bd5217bb Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 5 Sep 2008 01:29:24 +0200 Subject: update map file --- src/map-file | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/map-file b/src/map-file index b6d3b63d..67a5ee36 100644 --- a/src/map-file +++ b/src/map-file @@ -9,6 +9,7 @@ pa_browser_unref; pa_bytes_per_second; pa_bytes_snprint; pa_bytes_to_usec; +pa_channel_map_compatible; pa_channel_map_equal; pa_channel_map_init; pa_channel_map_init_auto; @@ -98,6 +99,7 @@ pa_context_unref; pa_cvolume_avg; pa_cvolume_channels_equal_to; pa_cvolume_equal; +pa_cvolume_max; pa_cvolume_remap; pa_cvolume_set; pa_cvolume_snprint; -- cgit From 34290725043274ddc88aeb203892f3d8bb7bbecf Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 5 Sep 2008 01:30:25 +0200 Subject: introduce upper channel map definition limit PA_CHANNEL_MAP_DEF_MAX --- src/pulse/channelmap.c | 4 +++- src/pulse/channelmap.h | 5 ++++- 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/pulse/channelmap.c b/src/pulse/channelmap.c index 7a21998e..7df6d6df 100644 --- a/src/pulse/channelmap.c +++ b/src/pulse/channelmap.c @@ -198,6 +198,7 @@ pa_channel_map* pa_channel_map_init_auto(pa_channel_map *m, unsigned channels, p pa_assert(m); pa_assert(channels > 0); pa_assert(channels <= PA_CHANNELS_MAX); + pa_assert(def < PA_CHANNEL_MAP_DEF_MAX); pa_channel_map_init(m); @@ -391,7 +392,7 @@ pa_channel_map* pa_channel_map_init_auto(pa_channel_map *m, unsigned channels, p default: - return NULL; + pa_assert_not_reached(); } } @@ -401,6 +402,7 @@ pa_channel_map* pa_channel_map_init_extend(pa_channel_map *m, unsigned channels, pa_assert(m); pa_assert(channels > 0); pa_assert(channels <= PA_CHANNELS_MAX); + pa_assert(def < PA_CHANNEL_MAP_DEF_MAX); pa_channel_map_init(m); diff --git a/src/pulse/channelmap.h b/src/pulse/channelmap.h index 035f9b1a..d2dd6f8f 100644 --- a/src/pulse/channelmap.h +++ b/src/pulse/channelmap.h @@ -157,6 +157,9 @@ typedef enum pa_channel_map_def { PA_CHANNEL_MAP_OSS, /**< The default channel mapping used by OSS as defined in the OSS 4.0 API specs */ + /**< Upper limit of valid channel mapping definitions */ + PA_CHANNEL_MAP_DEF_MAX, + PA_CHANNEL_MAP_DEFAULT = PA_CHANNEL_MAP_AIFF /**< The default channel map */ } pa_channel_map_def_t; @@ -211,7 +214,7 @@ pa_channel_map *pa_channel_map_parse(pa_channel_map *map, const char *s); /** Compare two channel maps. Return 1 if both match. */ int pa_channel_map_equal(const pa_channel_map *a, const pa_channel_map *b) PA_GCC_PURE; -/** Return non-zero of the specified channel map is considered valid */ +/** Return non-zero if the specified channel map is considered valid */ int pa_channel_map_valid(const pa_channel_map *map) PA_GCC_PURE; /** Return non-zero if the specified channel map is compatible with -- cgit From b56f344b97e9520828a76cf54d81663fa48cbd33 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 5 Sep 2008 01:30:48 +0200 Subject: a few minor clean-ups --- src/pulse/channelmap.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/pulse/channelmap.c b/src/pulse/channelmap.c index 7df6d6df..37308751 100644 --- a/src/pulse/channelmap.c +++ b/src/pulse/channelmap.c @@ -288,9 +288,6 @@ pa_channel_map* pa_channel_map_init_auto(pa_channel_map *m, unsigned channels, p case PA_CHANNEL_MAP_AUX: { unsigned i; - if (channels >= PA_CHANNELS_MAX) - return NULL; - for (i = 0; i < channels; i++) m->map[i] = PA_CHANNEL_POSITION_AUX0 + i; @@ -491,7 +488,7 @@ pa_channel_map *pa_channel_map_parse(pa_channel_map *rmap, const char *s) { pa_assert(rmap); pa_assert(s); - memset(&map, 0, sizeof(map)); + pa_channel_map_init(&map); if (strcmp(s, "stereo") == 0) { map.channels = 2; @@ -554,11 +551,9 @@ int pa_channel_map_valid(const pa_channel_map *map) { if (map->channels <= 0 || map->channels > PA_CHANNELS_MAX) return 0; - for (c = 0; c < map->channels; c++) { - - if (map->map[c] < 0 ||map->map[c] >= PA_CHANNEL_POSITION_MAX) + for (c = 0; c < map->channels; c++) + if (map->map[c] < 0 || map->map[c] >= PA_CHANNEL_POSITION_MAX) return 0; - } return 1; } -- cgit From 3f6f13f90227d1adfe39b56671aa34745778f35d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 5 Sep 2008 01:31:17 +0200 Subject: use pa_channel_map_compatible() where applicable --- src/utils/pacat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/utils/pacat.c b/src/utils/pacat.c index f42abc8e..76aea36a 100644 --- a/src/utils/pacat.c +++ b/src/utils/pacat.c @@ -695,7 +695,7 @@ int main(int argc, char *argv[]) { goto quit; } - if (channel_map_set && channel_map.channels != sample_spec.channels) { + if (channel_map_set && pa_channel_map_compatible(&channel_map, &sample_spec)) { fprintf(stderr, _("Channel map doesn't match sample specification\n")); goto quit; } -- cgit From a609e4a700da10926fcb9c9633dee1342907de97 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 5 Sep 2008 01:31:39 +0200 Subject: check for errors returned by pa_context_connect() --- src/utils/pacat.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/utils/pacat.c b/src/utils/pacat.c index 76aea36a..99df5b9e 100644 --- a/src/utils/pacat.c +++ b/src/utils/pacat.c @@ -773,7 +773,10 @@ int main(int argc, char *argv[]) { pa_context_set_state_callback(context, context_state_callback, NULL); /* Connect the context */ - pa_context_connect(context, server, 0, NULL); + if (pa_context_connect(context, server, 0, NULL) < 0) { + fprintf(stderr, _("pa_context_connect() failed: %s"), pa_strerror(pa_context_errno(context))); + goto quit; + } if (verbose) { struct timeval tv; -- cgit From f52fb64313fd423cd085f7b53ce5663c0c17d382 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 5 Sep 2008 03:17:48 +0200 Subject: if we are exiting due to idleness, say so --- src/pulsecore/core.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/pulsecore/core.c b/src/pulsecore/core.c index b9f04b68..6f8a2929 100644 --- a/src/pulsecore/core.c +++ b/src/pulsecore/core.c @@ -204,6 +204,7 @@ static void exit_callback(pa_mainloop_api*m, pa_time_event *e, const struct time pa_core *c = userdata; pa_assert(c->exit_event == e); + pa_log_info("We are idle, quitting..."); pa_core_exit(c, TRUE, 0); } -- cgit From 89ed50750e46486ba06638f15f3bb32e92e5c903 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 5 Sep 2008 03:18:36 +0200 Subject: if we are exiting due to cpu overload, say so via syslog, too --- src/daemon/cpulimit.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/daemon/cpulimit.c b/src/daemon/cpulimit.c index 59552828..a909600e 100644 --- a/src/daemon/cpulimit.c +++ b/src/daemon/cpulimit.c @@ -167,6 +167,8 @@ static void callback(pa_mainloop_api*m, pa_io_event*e, int fd, pa_io_event_flags pa_assert(e == io_event); pa_assert(fd == the_pipe[0]); + pa_log("Recevied request to terminate due to CPU overload."); + pa_read(the_pipe[0], &c, sizeof(c), NULL); m->quit(m, 1); /* Quit the main loop */ } -- cgit From 994ff984f04740e6817f3eb7b725e3825f3d290c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 5 Sep 2008 03:20:33 +0200 Subject: connect to localhost via IP address instead of host name, to avoid needless NSS lookup --- src/pulse/context.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/pulse/context.c b/src/pulse/context.c index f1aa4987..723980e1 100644 --- a/src/pulse/context.c +++ b/src/pulse/context.c @@ -905,8 +905,9 @@ int pa_context_connect( pa_xfree(d); } - c->server_list = pa_strlist_prepend(c->server_list, "tcp6:localhost"); - c->server_list = pa_strlist_prepend(c->server_list, "tcp4:localhost"); + /* Add TCP/IP on the localhost */ + c->server_list = pa_strlist_prepend(c->server_list, "tcp6:[::1]"); + c->server_list = pa_strlist_prepend(c->server_list, "tcp4:127.0.0.1"); /* The system wide instance */ c->server_list = pa_strlist_prepend(c->server_list, PA_SYSTEM_RUNTIME_PATH PA_PATH_SEP PA_NATIVE_DEFAULT_UNIX_SOCKET); -- cgit From fb837f0cac00d0207f84c9e68e1f7c2d6cd33a51 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 5 Sep 2008 03:22:13 +0200 Subject: rework autospawning to allow to multiple parallel autospawning contexts --- src/pulse/context.c | 313 ++++++++++++++++++--------------------------------- src/pulse/internal.h | 3 - 2 files changed, 107 insertions(+), 209 deletions(-) (limited to 'src') diff --git a/src/pulse/context.c b/src/pulse/context.c index 723980e1..154e5faf 100644 --- a/src/pulse/context.c +++ b/src/pulse/context.c @@ -54,7 +54,6 @@ #include #include #include -#include #include #include @@ -98,26 +97,6 @@ static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = { [PA_COMMAND_SUBSCRIBE_EVENT] = pa_command_subscribe_event, [PA_COMMAND_EXTENSION] = pa_command_extension }; - -static void unlock_autospawn(pa_context *c) { - pa_assert(c); - - if (c->autospawn_fd >= 0) { - - if (c->autospawn_locked) - pa_autospawn_lock_release(); - - if (c->autospawn_event) - c->mainloop->io_free(c->autospawn_event); - - pa_autospawn_lock_done(FALSE); - } - - c->autospawn_locked = FALSE; - c->autospawn_fd = -1; - c->autospawn_event = NULL; -} - static void context_free(pa_context *c); pa_context *pa_context_new(pa_mainloop_api *mainloop, const char *name) { @@ -180,9 +159,6 @@ pa_context *pa_context_new_with_proplist(pa_mainloop_api *mainloop, const char * c->do_shm = FALSE; c->do_autospawn = FALSE; - c->autospawn_fd = -1; - c->autospawn_locked = FALSE; - c->autospawn_event = NULL; memset(&c->spawn_api, 0, sizeof(c->spawn_api)); #ifndef MSG_NOSIGNAL @@ -252,8 +228,6 @@ static void context_free(pa_context *c) { context_unlink(c); - unlock_autospawn(c); - if (c->record_streams) pa_dynarray_free(c->record_streams, NULL, NULL); if (c->playback_streams) @@ -577,31 +551,89 @@ static void setup_context(pa_context *c, pa_iochannel *io) { pa_context_unref(c); } -static void on_connection(pa_socket_client *client, pa_iochannel*io, void *userdata); +static char *get_old_legacy_runtime_dir(void) { + char *p, u[128]; + struct stat st; -#ifndef OS_IS_WIN32 + if (!pa_get_user_name(u, sizeof(u))) + return NULL; -static int context_connect_spawn(pa_context *c) { - pid_t pid; - int status, r; - int fds[2] = { -1, -1} ; - pa_iochannel *io; + p = pa_sprintf_malloc("/tmp/pulse-%s", u); - if (getuid() == 0) - return -1; + if (stat(p, &st) < 0) { + pa_xfree(p); + return NULL; + } - pa_context_ref(c); + if (st.st_uid != getuid()) { + pa_xfree(p); + return NULL; + } - if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) { - pa_log_error(_("socketpair(): %s"), pa_cstrerror(errno)); - pa_context_fail(c, PA_ERR_INTERNAL); - goto fail; + return p; +} + +static char *get_very_old_legacy_runtime_dir(void) { + char *p, h[128]; + struct stat st; + + if (!pa_get_home_dir(h, sizeof(h))) + return NULL; + + p = pa_sprintf_malloc("%s/.pulse", h); + + if (stat(p, &st) < 0) { + pa_xfree(p); + return NULL; + } + + if (st.st_uid != getuid()) { + pa_xfree(p); + return NULL; + } + + return p; +} + + +static pa_strlist *prepend_per_user(pa_strlist *l) { + char *ufn; + static char *legacy_dir; + + /* The very old per-user instance path (< 0.9.11). This is supported only to ease upgrades */ + if ((legacy_dir = get_very_old_legacy_runtime_dir())) { + char *p = pa_sprintf_malloc("%s" PA_PATH_SEP PA_NATIVE_DEFAULT_UNIX_SOCKET, legacy_dir); + l = pa_strlist_prepend(l, p); + pa_xfree(p); + pa_xfree(legacy_dir); + } + + /* The old per-user instance path (< 0.9.12). This is supported only to ease upgrades */ + if ((legacy_dir = get_old_legacy_runtime_dir())) { + char *p = pa_sprintf_malloc("%s" PA_PATH_SEP PA_NATIVE_DEFAULT_UNIX_SOCKET, legacy_dir); + l = pa_strlist_prepend(l, p); + pa_xfree(p); + pa_xfree(legacy_dir); } - pa_make_fd_cloexec(fds[0]); + /* The per-user instance */ + if ((ufn = pa_runtime_path(PA_NATIVE_DEFAULT_UNIX_SOCKET))) { + l = pa_strlist_prepend(l, ufn); + pa_xfree(ufn); + } + + return l; +} - pa_make_socket_low_delay(fds[0]); - pa_make_socket_low_delay(fds[1]); +#ifndef OS_IS_WIN32 + +static int context_autospawn(pa_context *c) { + pid_t pid; + int status, r; + + pa_log_debug("Trying to autospawn..."); + + pa_context_ref(c); if (c->spawn_api.prefork) c->spawn_api.prefork(); @@ -617,31 +649,22 @@ static int context_connect_spawn(pa_context *c) { } else if (!pid) { /* Child */ - char t[128]; const char *state = NULL; #define MAX_ARGS 64 const char * argv[MAX_ARGS+1]; int n; - char *f; - - pa_close_all(fds[1], -1); - - f = pa_sprintf_malloc("%i", fds[1]); - pa_set_env("PULSE_PASSED_FD", f); - pa_xfree(f); if (c->spawn_api.atfork) c->spawn_api.atfork(); + pa_close_all(-1); + /* Setup argv */ n = 0; argv[n++] = c->conf->daemon_binary; - argv[n++] = "--daemonize=yes"; - - pa_snprintf(t, sizeof(t), "-Lmodule-native-protocol-fd fd=%i", fds[1]); - argv[n++] = strdup(t); + argv[n++] = "--start"; while (n < MAX_ARGS) { char *a; @@ -661,14 +684,13 @@ static int context_connect_spawn(pa_context *c) { /* Parent */ - pa_assert_se(pa_close(fds[1]) == 0); - fds[1] = -1; - - r = waitpid(pid, &status, 0); - if (c->spawn_api.postfork) c->spawn_api.postfork(); + do { + r = waitpid(pid, &status, 0); + } while (r < 0 && errno == EINTR); + if (r < 0) { pa_log(_("waitpid(): %s"), pa_cstrerror(errno)); pa_context_fail(c, PA_ERR_INTERNAL); @@ -678,21 +700,11 @@ static int context_connect_spawn(pa_context *c) { goto fail; } - c->is_local = TRUE; - - unlock_autospawn(c); - - io = pa_iochannel_new(c->mainloop, fds[0], fds[0]); - setup_context(c, io); - pa_context_unref(c); return 0; fail: - pa_close_pipe(fds); - - unlock_autospawn(c); pa_context_unref(c); @@ -701,6 +713,8 @@ fail: #endif /* OS_IS_WIN32 */ +static void on_connection(pa_socket_client *client, pa_iochannel*io, void *userdata); + static int try_next_connection(pa_context *c) { char *u = NULL; int r = -1; @@ -718,8 +732,18 @@ static int try_next_connection(pa_context *c) { #ifndef OS_IS_WIN32 if (c->do_autospawn) { - r = context_connect_spawn(c); - goto finish; + + if ((r = context_autospawn(c)) < 0) + goto finish; + + /* Autospawn only once */ + c->do_autospawn = FALSE; + + /* Connect only to per-user sockets this time */ + c->server_list = prepend_per_user(c->server_list); + + /* Retry connection */ + continue; } #endif @@ -774,91 +798,12 @@ static void on_connection(pa_socket_client *client, pa_iochannel*io, void *userd goto finish; } - unlock_autospawn(c); setup_context(c, io); finish: pa_context_unref(c); } -static void autospawn_cb(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags_t events, void *userdata) { - pa_context *c = userdata; - int k; - - pa_assert(a); - pa_assert(e); - pa_assert(fd >= 0); - pa_assert(events == PA_IO_EVENT_INPUT); - pa_assert(c); - pa_assert(e == c->autospawn_event); - pa_assert(fd == c->autospawn_fd); - - pa_context_ref(c); - - /* Check whether we can get the lock right now*/ - if ((k = pa_autospawn_lock_acquire(FALSE)) < 0) { - pa_context_fail(c, PA_ERR_ACCESS); - goto finish; - } - - if (k > 0) { - /* So we got it, rock on! */ - c->autospawn_locked = TRUE; - try_next_connection(c); - - c->mainloop->io_free(c->autospawn_event); - c->autospawn_event = NULL; - } - -finish: - - pa_context_unref(c); -} - -static char *get_old_legacy_runtime_dir(void) { - char *p, u[128]; - struct stat st; - - if (!pa_get_user_name(u, sizeof(u))) - return NULL; - - p = pa_sprintf_malloc("/tmp/pulse-%s", u); - - if (stat(p, &st) < 0) { - pa_xfree(p); - return NULL; - } - - if (st.st_uid != getuid()) { - pa_xfree(p); - return NULL; - } - - return p; -} - -static char *get_very_old_legacy_runtime_dir(void) { - char *p, h[128]; - struct stat st; - - if (!pa_get_home_dir(h, sizeof(h))) - return NULL; - - p = pa_sprintf_malloc("%s/.pulse", h); - - if (stat(p, &st) < 0) { - pa_xfree(p); - return NULL; - } - - if (st.st_uid != getuid()) { - pa_xfree(p); - return NULL; - } - - return p; -} - int pa_context_connect( pa_context *c, const char *server, @@ -888,11 +833,11 @@ int pa_context_connect( } } else { - char *d, *ufn; - static char *legacy_dir; + char *d; /* Prepend in reverse order */ + /* Follow the X display */ if ((d = getenv("DISPLAY"))) { char *e; d = pa_xstrdup(d); @@ -909,67 +854,23 @@ int pa_context_connect( c->server_list = pa_strlist_prepend(c->server_list, "tcp6:[::1]"); c->server_list = pa_strlist_prepend(c->server_list, "tcp4:127.0.0.1"); - /* The system wide instance */ + /* The system wide instance via PF_LOCAL */ c->server_list = pa_strlist_prepend(c->server_list, PA_SYSTEM_RUNTIME_PATH PA_PATH_SEP PA_NATIVE_DEFAULT_UNIX_SOCKET); - /* The very old per-user instance path (< 0.9.11). This is supported only to ease upgrades */ - if ((legacy_dir = get_very_old_legacy_runtime_dir())) { - char *p = pa_sprintf_malloc("%s" PA_PATH_SEP PA_NATIVE_DEFAULT_UNIX_SOCKET, legacy_dir); - c->server_list = pa_strlist_prepend(c->server_list, p); - pa_xfree(p); - pa_xfree(legacy_dir); - } + /* The user instance via PF_LOCAL */ + c->server_list = prepend_per_user(c->server_list); - /* The old per-user instance path (< 0.9.12). This is supported only to ease upgrades */ - if ((legacy_dir = get_old_legacy_runtime_dir())) { - char *p = pa_sprintf_malloc("%s" PA_PATH_SEP PA_NATIVE_DEFAULT_UNIX_SOCKET, legacy_dir); - c->server_list = pa_strlist_prepend(c->server_list, p); - pa_xfree(p); - pa_xfree(legacy_dir); - } - - /* The per-user instance */ - if ((ufn = pa_runtime_path(PA_NATIVE_DEFAULT_UNIX_SOCKET))) { - c->server_list = pa_strlist_prepend(c->server_list, ufn); - pa_xfree(ufn); - } - - /* Wrap the connection attempts in a single transaction for sane autospawn locking */ + /* Set up autospawning */ if (!(flags & PA_CONTEXT_NOAUTOSPAWN) && c->conf->autospawn) { - int k; - - pa_assert(c->autospawn_fd < 0); - pa_assert(!c->autospawn_locked); - /* Start the locking procedure */ - if ((c->autospawn_fd = pa_autospawn_lock_init()) < 0) { - pa_context_fail(c, PA_ERR_ACCESS); - goto finish; - } - - if (api) - c->spawn_api = *api; - - c->do_autospawn = TRUE; - - /* Check whether we can get the lock right now*/ - if ((k = pa_autospawn_lock_acquire(FALSE)) < 0) { - pa_context_fail(c, PA_ERR_ACCESS); - goto finish; - } - - if (k > 0) - /* So we got it, rock on! */ - c->autospawn_locked = TRUE; + if (getuid() == 0) + pa_log_debug("Not doing autospawn since we are root."); else { - /* Hmm, we didn't get it, so let's wait for it */ - c->autospawn_event = c->mainloop->io_new(c->mainloop, c->autospawn_fd, PA_IO_EVENT_INPUT, autospawn_cb, c); + c->do_autospawn = TRUE; - pa_context_set_state(c, PA_CONTEXT_CONNECTING); - r = 0; - goto finish; + if (api) + c->spawn_api = *api; } - } } diff --git a/src/pulse/internal.h b/src/pulse/internal.h index 9167bf1b..5fe4210e 100644 --- a/src/pulse/internal.h +++ b/src/pulse/internal.h @@ -78,9 +78,6 @@ struct pa_context { pa_bool_t do_shm:1; pa_bool_t do_autospawn:1; - pa_bool_t autospawn_locked:1; - int autospawn_fd; - pa_io_event *autospawn_event; pa_spawn_api spawn_api; pa_strlist *server_list; -- cgit From 33d349dcbbef0952e9e59ca105e08fdff5454803 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 5 Sep 2008 15:42:39 +0300 Subject: include build and runtime host information in debug output --- src/daemon/main.c | 9 +++++++-- src/pulsecore/core-util.c | 8 ++++++++ src/pulsecore/core-util.h | 1 + 3 files changed, 16 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/daemon/main.c b/src/daemon/main.c index c8eda398..bb8af444 100644 --- a/src/daemon/main.c +++ b/src/daemon/main.c @@ -778,8 +778,15 @@ int main(int argc, char *argv[]) { pa_set_env("PULSE_SYSTEM", conf->system_instance ? "1" : "0"); 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); + s = pa_uname_string(); + pa_log_debug(_("Running on host: %s"), s); + pa_xfree(s); + + pa_log_info(_("Page size is %lu bytes"), (unsigned long) PA_PAGE_SIZE); + #ifdef HAVE_VALGRIND_MEMCHECK_H pa_log_debug(_("Compiled with Valgrind support: yes")); #else @@ -792,8 +799,6 @@ int main(int argc, char *argv[]) { pa_log_debug(_("Optimized build: no")); #endif - pa_log_info(_("Page size is %lu bytes"), (unsigned long) PA_PAGE_SIZE); - if (!(s = pa_machine_id())) { pa_log(_("Failed to get machine ID")); goto finish; diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c index ad00f4f4..3e5ea492 100644 --- a/src/pulsecore/core-util.c +++ b/src/pulsecore/core-util.c @@ -42,6 +42,7 @@ #include #include #include +#include #ifdef HAVE_STRTOF_L #include @@ -2445,5 +2446,12 @@ char *pa_machine_id(void) { /* If no hostname was set we use the POSIX hostid. It's usually * the IPv4 address. Mit not be that stable. */ return pa_sprintf_malloc("%08lx", (unsigned long) gethostid); +} + +char *pa_uname_string(void) { + struct utsname u; + + pa_assert_se(uname(&u) == 0); + return pa_sprintf_malloc("%s %s %s %s", u.sysname, u.machine, u.release, u.version); } diff --git a/src/pulsecore/core-util.h b/src/pulsecore/core-util.h index c9e307f5..df8ce3f8 100644 --- a/src/pulsecore/core-util.h +++ b/src/pulsecore/core-util.h @@ -191,5 +191,6 @@ pa_bool_t pa_in_system_mode(void); #define pa_streq(a,b) (!strcmp((a),(b))) char *pa_machine_id(void); +char *pa_uname_string(void); #endif -- cgit From f2164023fd0fda8c1a456c5c2f144f8943c24db9 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 5 Sep 2008 16:04:42 +0300 Subject: Add new option to disable remixing from/to LFE and set it to on by default --- src/daemon/daemon-conf.c | 36 ++++++++++++++++++++---------------- src/daemon/daemon-conf.h | 1 + src/daemon/daemon.conf.in | 1 + src/daemon/main.c | 1 + src/pulsecore/core.c | 1 + src/pulsecore/core.h | 1 + src/pulsecore/resampler.c | 8 ++++++-- src/pulsecore/resampler.h | 7 ++++--- src/pulsecore/sink-input.c | 3 ++- src/pulsecore/source-output.c | 3 ++- 10 files changed, 39 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/daemon/daemon-conf.c b/src/daemon/daemon-conf.c index 40e0a170..77da3f7e 100644 --- a/src/daemon/daemon-conf.c +++ b/src/daemon/daemon-conf.c @@ -76,6 +76,7 @@ static const pa_daemon_conf default_conf = { .log_level = PA_LOG_NOTICE, .resample_method = PA_RESAMPLER_AUTO, .disable_remixing = FALSE, + .disable_lfe_remixing = TRUE, .config_file = NULL, .use_pid_file = TRUE, .system_instance = FALSE, @@ -426,6 +427,7 @@ int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) { { "default-fragment-size-msec", parse_fragment_size_msec, NULL }, { "nice-level", parse_nice_level, NULL }, { "disable-remixing", pa_config_parse_bool, NULL }, + { "disable-lfe-remixing", pa_config_parse_bool, NULL }, { "load-default-script-file", pa_config_parse_bool, NULL }, #ifdef HAVE_SYS_RESOURCE_H { "rlimit-fsize", parse_rlimit, NULL }, @@ -490,66 +492,67 @@ int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) { table[24].data = c; table[25].data = c; table[26].data = &c->disable_remixing; - table[27].data = &c->load_default_script_file; + table[27].data = &c->disable_lfe_remixing; + table[28].data = &c->load_default_script_file; #ifdef HAVE_SYS_RESOURCE_H - table[28].data = &c->rlimit_fsize; - table[29].data = &c->rlimit_data; - table[30].data = &c->rlimit_stack; - table[31].data = &c->rlimit_as; - table[32].data = &c->rlimit_core; - table[33].data = &c->rlimit_nofile; - table[34].data = &c->rlimit_as; + table[29].data = &c->rlimit_fsize; + table[30].data = &c->rlimit_data; + table[31].data = &c->rlimit_stack; + table[32].data = &c->rlimit_as; + table[33].data = &c->rlimit_core; + table[34].data = &c->rlimit_nofile; + table[35].data = &c->rlimit_as; #ifdef RLIMIT_NPROC - table[35].data = &c->rlimit_nproc; + table[36].data = &c->rlimit_nproc; #endif #ifdef RLIMIT_MEMLOCK #ifndef RLIMIT_NPROC #error "Houston, we have a numbering problem!" #endif - table[36].data = &c->rlimit_memlock; + table[37].data = &c->rlimit_memlock; #endif #ifdef RLIMIT_LOCKS #ifndef RLIMIT_MEMLOCK #error "Houston, we have a numbering problem!" #endif - table[37].data = &c->rlimit_locks; + table[38].data = &c->rlimit_locks; #endif #ifdef RLIMIT_SIGPENDING #ifndef RLIMIT_LOCKS #error "Houston, we have a numbering problem!" #endif - table[38].data = &c->rlimit_sigpending; + table[39].data = &c->rlimit_sigpending; #endif #ifdef RLIMIT_MSGQUEUE #ifndef RLIMIT_SIGPENDING #error "Houston, we have a numbering problem!" #endif - table[39].data = &c->rlimit_msgqueue; + table[40].data = &c->rlimit_msgqueue; #endif #ifdef RLIMIT_NICE #ifndef RLIMIT_MSGQUEUE #error "Houston, we have a numbering problem!" #endif - table[40].data = &c->rlimit_nice; + table[41].data = &c->rlimit_nice; #endif #ifdef RLIMIT_RTPRIO #ifndef RLIMIT_NICE #error "Houston, we have a numbering problem!" #endif - table[41].data = &c->rlimit_rtprio; + table[42].data = &c->rlimit_rtprio; #endif #ifdef RLIMIT_RTTIME #ifndef RLIMIT_RTTIME #error "Houston, we have a numbering problem!" #endif - table[42].data = &c->rlimit_rttime; + table[43].data = &c->rlimit_rttime; #endif #endif @@ -661,6 +664,7 @@ char *pa_daemon_conf_dump(pa_daemon_conf *c) { pa_strbuf_printf(s, "log-level = %s\n", log_level_to_string[c->log_level]); pa_strbuf_printf(s, "resample-method = %s\n", pa_resample_method_to_string(c->resample_method)); pa_strbuf_printf(s, "disable-remixing = %s\n", pa_yes_no(c->disable_remixing)); + pa_strbuf_printf(s, "disable-lfe-remixing = %s\n", pa_yes_no(c->disable_lfe_remixing)); pa_strbuf_printf(s, "default-sample-format = %s\n", pa_sample_format_to_string(c->default_sample_spec.format)); pa_strbuf_printf(s, "default-sample-rate = %u\n", c->default_sample_spec.rate); pa_strbuf_printf(s, "default-sample-channels = %u\n", c->default_sample_spec.channels); diff --git a/src/daemon/daemon-conf.h b/src/daemon/daemon-conf.h index c42984f9..309a1428 100644 --- a/src/daemon/daemon-conf.h +++ b/src/daemon/daemon-conf.h @@ -66,6 +66,7 @@ typedef struct pa_daemon_conf { no_cpu_limit, disable_shm, disable_remixing, + disable_lfe_remixing, load_default_script_file, disallow_exit; int exit_idle_time, diff --git a/src/daemon/daemon.conf.in b/src/daemon/daemon.conf.in index 33b1d61d..ea09fe09 100644 --- a/src/daemon/daemon.conf.in +++ b/src/daemon/daemon.conf.in @@ -47,6 +47,7 @@ ; resample-method = speex-float-3 ; disable-remixing = no +; disable-lfe-remixing = yes ; no-cpu-limit = no diff --git a/src/daemon/main.c b/src/daemon/main.c index bb8af444..f91573b4 100644 --- a/src/daemon/main.c +++ b/src/daemon/main.c @@ -869,6 +869,7 @@ int main(int argc, char *argv[]) { c->realtime_priority = conf->realtime_priority; c->realtime_scheduling = !!conf->realtime_scheduling; c->disable_remixing = !!conf->disable_remixing; + c->disable_lfe_remixing = !!conf->disable_lfe_remixing; c->running_as_daemon = !!conf->daemonize; c->disallow_exit = conf->disallow_exit; diff --git a/src/pulsecore/core.c b/src/pulsecore/core.c index 6f8a2929..bd956ae0 100644 --- a/src/pulsecore/core.c +++ b/src/pulsecore/core.c @@ -138,6 +138,7 @@ pa_core* pa_core_new(pa_mainloop_api *m, int shared) { c->realtime_scheduling = FALSE; c->realtime_priority = 5; c->disable_remixing = FALSE; + c->disable_lfe_remixing = FALSE; for (j = 0; j < PA_CORE_HOOK_MAX; j++) pa_hook_init(&c->hooks[j], c); diff --git a/src/pulsecore/core.h b/src/pulsecore/core.h index eb768418..fb4490f2 100644 --- a/src/pulsecore/core.h +++ b/src/pulsecore/core.h @@ -124,6 +124,7 @@ struct pa_core { pa_bool_t running_as_daemon:1; pa_bool_t realtime_scheduling:1; pa_bool_t disable_remixing:1; + pa_bool_t disable_lfe_remixing:1; pa_resample_method_t resample_method; int realtime_priority; diff --git a/src/pulsecore/resampler.c b/src/pulsecore/resampler.c index 45cd68c1..0ae029b3 100644 --- a/src/pulsecore/resampler.c +++ b/src/pulsecore/resampler.c @@ -716,7 +716,11 @@ static void calc_map_table(pa_resampler *r) { * channels for LFE. */ for (ic = 0; ic < r->i_ss.channels; ic++) { - r->map_table[oc][ic] = 1.0f / (float) r->i_ss.channels; + + if (!(r->flags & PA_RESAMPLER_NO_LFE)) + r->map_table[oc][ic] = 1.0f / (float) r->i_ss.channels; + else + r->map_table[oc][ic] = 0; /* Please note that a channel connected to LFE * doesn't really count as connected. */ @@ -851,7 +855,7 @@ static void calc_map_table(pa_resampler *r) { } } - if (ic_unconnected_lfe > 0) { + if (ic_unconnected_lfe > 0 && !(r->flags & PA_RESAMPLER_NO_LFE)) { /* OK, so there is an unconnected LFE channel. Let's mix * it into all channels, with factor 0.375 */ diff --git a/src/pulsecore/resampler.h b/src/pulsecore/resampler.h index 5e302a9b..87110cc2 100644 --- a/src/pulsecore/resampler.h +++ b/src/pulsecore/resampler.h @@ -49,9 +49,10 @@ typedef enum pa_resample_method { } pa_resample_method_t; typedef enum pa_resample_flags { - PA_RESAMPLER_VARIABLE_RATE = 1, - PA_RESAMPLER_NO_REMAP = 2, /* implies NO_REMIX */ - PA_RESAMPLER_NO_REMIX = 4 + PA_RESAMPLER_VARIABLE_RATE = 0x0001U, + PA_RESAMPLER_NO_REMAP = 0x0002U, /* implies NO_REMIX */ + PA_RESAMPLER_NO_REMIX = 0x0004U, + PA_RESAMPLER_NO_LFE = 0x0008U } pa_resample_flags_t; pa_resampler* pa_resampler_new( diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c index 7d80242f..326a7e2c 100644 --- a/src/pulsecore/sink-input.c +++ b/src/pulsecore/sink-input.c @@ -201,7 +201,8 @@ pa_sink_input* pa_sink_input_new( data->resample_method, ((flags & PA_SINK_INPUT_VARIABLE_RATE) ? PA_RESAMPLER_VARIABLE_RATE : 0) | ((flags & PA_SINK_INPUT_NO_REMAP) ? PA_RESAMPLER_NO_REMAP : 0) | - (core->disable_remixing || (flags & PA_SINK_INPUT_NO_REMIX) ? PA_RESAMPLER_NO_REMIX : 0)))) { + (core->disable_remixing || (flags & PA_SINK_INPUT_NO_REMIX) ? PA_RESAMPLER_NO_REMIX : 0) | + (core->disable_lfe_remixing ? PA_RESAMPLER_NO_LFE : 0)))) { pa_log_warn("Unsupported resampling operation."); return NULL; } diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c index 5df950a8..d76f6e4e 100644 --- a/src/pulsecore/source-output.c +++ b/src/pulsecore/source-output.c @@ -171,7 +171,8 @@ pa_source_output* pa_source_output_new( data->resample_method, ((flags & PA_SOURCE_OUTPUT_VARIABLE_RATE) ? PA_RESAMPLER_VARIABLE_RATE : 0) | ((flags & PA_SOURCE_OUTPUT_NO_REMAP) ? PA_RESAMPLER_NO_REMAP : 0) | - (core->disable_remixing || (flags & PA_SOURCE_OUTPUT_NO_REMIX) ? PA_RESAMPLER_NO_REMIX : 0)))) { + (core->disable_remixing || (flags & PA_SOURCE_OUTPUT_NO_REMIX) ? PA_RESAMPLER_NO_REMIX : 0) | + (core->disable_lfe_remixing ? PA_RESAMPLER_NO_LFE : 0)))) { pa_log_warn("Unsupported resampling operation."); return NULL; } -- cgit From 821dc1797faa903618c7585d3c053fd7ae6e93db Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 8 Sep 2008 17:22:27 +0300 Subject: move autospawn lock to pulsecore/ since we don't need it in the client anymore --- src/Makefile.am | 7 +- src/daemon/main.c | 2 +- src/pulse/lock-autospawn.c | 330 ---------------------------------------- src/pulse/lock-autospawn.h | 32 ---- src/pulsecore/lock-autospawn.c | 330 ++++++++++++++++++++++++++++++++++++++++ src/pulsecore/lock-autospawn.h | 32 ++++ src/tests/lock-autospawn-test.c | 2 +- 7 files changed, 367 insertions(+), 368 deletions(-) delete mode 100644 src/pulse/lock-autospawn.c delete mode 100644 src/pulse/lock-autospawn.h create mode 100644 src/pulsecore/lock-autospawn.c create mode 100644 src/pulsecore/lock-autospawn.h (limited to 'src') diff --git a/src/Makefile.am b/src/Makefile.am index 3ee53722..1663d66d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -541,8 +541,7 @@ libpulse_la_SOURCES = \ pulse/xmalloc.c pulse/xmalloc.h \ pulse/proplist.c pulse/proplist.h \ pulse/ext-stream-restore.c pulse/ext-stream-restore.h \ - pulse/i18n.c pulse/i18n.h \ - pulse/lock-autospawn.c pulse/lock-autospawn.h + pulse/i18n.c pulse/i18n.h # Internal stuff that is shared with libpulsecore libpulse_la_SOURCES += \ @@ -740,8 +739,7 @@ libpulsecore_la_SOURCES = \ pulse/volume.c pulse/volume.h \ pulse/xmalloc.c pulse/xmalloc.h \ pulse/proplist.c pulse/proplist.h \ - pulse/i18n.c pulse/i18n.h \ - pulse/lock-autospawn.c pulse/lock-autospawn.h + pulse/i18n.c pulse/i18n.h # Pure core stuff (some are shared in libpulse though). libpulsecore_la_SOURCES += \ @@ -811,6 +809,7 @@ libpulsecore_la_SOURCES += \ pulsecore/start-child.c pulsecore/start-child.h \ pulsecore/envelope.c pulsecore/envelope.h \ pulsecore/proplist-util.c pulsecore/proplist-util.h \ + pulsecore/lock-autospawn.c pulsecore/lock-autospawn.h \ $(PA_THREAD_OBJS) if OS_IS_WIN32 diff --git a/src/daemon/main.c b/src/daemon/main.c index f91573b4..a9e8ed46 100644 --- a/src/daemon/main.c +++ b/src/daemon/main.c @@ -65,8 +65,8 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/pulse/lock-autospawn.c b/src/pulse/lock-autospawn.c deleted file mode 100644 index d36b669e..00000000 --- a/src/pulse/lock-autospawn.c +++ /dev/null @@ -1,330 +0,0 @@ -/*** - This file is part of PulseAudio. - - Copyright 2008 Lennart Poettering - - PulseAudio is free software; you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published - by the Free Software Foundation; either version 2 of the License, - or (at your option) any later version. - - PulseAudio is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with PulseAudio; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA. -***/ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include - -#include "lock-autospawn.h" - -/* So, why do we have this complex code here with threads and pipes - * and stuff? For two reasons: POSIX file locks are per-process, not - * per-file descriptor. That means that two contexts within the same - * process that try to create the autospawn lock might end up assuming - * they both managed to lock the file. And then, POSIX locking - * operations are synchronous. If two contexts run from the same event - * loop it must be made sure that they do not block each other, but - * that the locking operation can happen asynchronously. */ - -#define AUTOSPAWN_LOCK "autospawn.lock" - -static pa_mutex *mutex; - -static unsigned n_ref = 0; -static int lock_fd = -1; -static pa_mutex *lock_fd_mutex = NULL; -static pa_bool_t taken = FALSE; -static pa_thread *thread; -static int pipe_fd[2] = { -1, -1 }; - -static void destroy_mutex(void) PA_GCC_DESTRUCTOR; - -static int ref(void) { - - if (n_ref > 0) { - - pa_assert(pipe_fd[0] >= 0); - pa_assert(pipe_fd[1] >= 0); - - n_ref++; - - return 0; - } - - pa_assert(lock_fd < 0); - pa_assert(!lock_fd_mutex); - pa_assert(!taken); - pa_assert(!thread); - pa_assert(pipe_fd[0] < 0); - pa_assert(pipe_fd[1] < 0); - - if (pipe(pipe_fd) < 0) - return -1; - - lock_fd_mutex = pa_mutex_new(FALSE, FALSE); - - pa_make_fd_cloexec(pipe_fd[0]); - pa_make_fd_cloexec(pipe_fd[1]); - - pa_make_fd_nonblock(pipe_fd[1]); - pa_make_fd_nonblock(pipe_fd[0]); - - n_ref = 1; - return 0; -} - -static void unref(pa_bool_t after_fork) { - - pa_assert(n_ref > 0); - pa_assert(pipe_fd[0] >= 0); - pa_assert(pipe_fd[1] >= 0); - pa_assert(lock_fd_mutex); - - n_ref--; - - if (n_ref > 0) - return; - - pa_assert(!taken); - - if (thread) { - pa_thread_free(thread); - thread = NULL; - } - - pa_mutex_lock(lock_fd_mutex); - if (lock_fd >= 0) { - - if (after_fork) - pa_close(lock_fd); - else { - char *lf; - - if (!(lf = pa_runtime_path(AUTOSPAWN_LOCK))) - pa_log_warn(_("Cannot access autospawn lock.")); - - pa_unlock_lockfile(lf, lock_fd); - pa_xfree(lf); - - lock_fd = -1; - } - } - pa_mutex_unlock(lock_fd_mutex); - - pa_mutex_free(lock_fd_mutex); - lock_fd_mutex = NULL; - - pa_close(pipe_fd[0]); - pa_close(pipe_fd[1]); - pipe_fd[0] = pipe_fd[1] = -1; -} - -static void ping(void) { - ssize_t s; - - pa_assert(pipe_fd[1] >= 0); - - for (;;) { - char x = 'x'; - - if ((s = write(pipe_fd[1], &x, 1)) == 1) - break; - - pa_assert(s < 0); - - if (errno == EAGAIN) - break; - - pa_assert(errno == EINTR); - } -} - -static void wait_for_ping(void) { - ssize_t s; - char x; - struct pollfd pfd; - int k; - - pa_assert(pipe_fd[0] >= 0); - - memset(&pfd, 0, sizeof(pfd)); - pfd.fd = pipe_fd[0]; - pfd.events = POLLIN; - - if ((k = poll(&pfd, 1, -1)) != 1) { - pa_assert(k < 0); - pa_assert(errno == EINTR); - } else if ((s = read(pipe_fd[0], &x, 1)) != 1) { - pa_assert(s < 0); - pa_assert(errno == EAGAIN); - } -} - -static void empty_pipe(void) { - char x[16]; - ssize_t s; - - pa_assert(pipe_fd[0] >= 0); - - if ((s = read(pipe_fd[0], &x, sizeof(x))) < 1) { - pa_assert(s < 0); - pa_assert(errno == EAGAIN); - } -} - -static void thread_func(void *u) { - int fd; - char *lf; - sigset_t fullset; - - /* No signals in this thread please */ - sigfillset(&fullset); - pthread_sigmask(SIG_BLOCK, &fullset, NULL); - - if (!(lf = pa_runtime_path(AUTOSPAWN_LOCK))) { - pa_log_warn(_("Cannot access autospawn lock.")); - goto finish; - } - - if ((fd = pa_lock_lockfile(lf)) < 0) - goto finish; - - pa_mutex_lock(lock_fd_mutex); - pa_assert(lock_fd < 0); - lock_fd = fd; - pa_mutex_unlock(lock_fd_mutex); - -finish: - pa_xfree(lf); - - ping(); -} - -static int start_thread(void) { - - if (!thread) - if (!(thread = pa_thread_new(thread_func, NULL))) - return -1; - - return 0; -} - -static void create_mutex(void) { - PA_ONCE_BEGIN { - mutex = pa_mutex_new(FALSE, FALSE); - } PA_ONCE_END; -} - -static void destroy_mutex(void) { - - if (mutex) - pa_mutex_free(mutex); -} - - -int pa_autospawn_lock_init(void) { - int ret = -1; - - create_mutex(); - pa_mutex_lock(mutex); - - if (ref() < 0) - ret = -1; - else - ret = pipe_fd[0]; - - pa_mutex_unlock(mutex); - - return ret; -} - -int pa_autospawn_lock_acquire(pa_bool_t block) { - int ret = -1; - - create_mutex(); - pa_mutex_lock(mutex); - pa_assert(n_ref >= 1); - - pa_mutex_lock(lock_fd_mutex); - - for (;;) { - - empty_pipe(); - - if (lock_fd >= 0 && !taken) { - taken = TRUE; - ret = 1; - break; - } - - if (lock_fd < 0) - if (start_thread() < 0) - break; - - if (!block) { - ret = 0; - break; - } - - pa_mutex_unlock(lock_fd_mutex); - pa_mutex_unlock(mutex); - - wait_for_ping(); - - pa_mutex_lock(mutex); - pa_mutex_lock(lock_fd_mutex); - } - - pa_mutex_unlock(lock_fd_mutex); - - pa_mutex_unlock(mutex); - - return ret; -} - -void pa_autospawn_lock_release(void) { - - create_mutex(); - pa_mutex_lock(mutex); - pa_assert(n_ref >= 1); - - pa_assert(taken); - taken = FALSE; - - ping(); - - pa_mutex_unlock(mutex); -} - -void pa_autospawn_lock_done(pa_bool_t after_fork) { - - create_mutex(); - pa_mutex_lock(mutex); - pa_assert(n_ref >= 1); - - unref(after_fork); - - pa_mutex_unlock(mutex); -} diff --git a/src/pulse/lock-autospawn.h b/src/pulse/lock-autospawn.h deleted file mode 100644 index c04c4bd1..00000000 --- a/src/pulse/lock-autospawn.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef foopulselockautospawnhfoo -#define foopulselockautospawnhfoo - -/*** - This file is part of PulseAudio. - - Copyright 2008 Lennart Poettering - - PulseAudio is free software; you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as - published by the Free Software Foundation; either version 2.1 of the - License, or (at your option) any later version. - - PulseAudio is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with PulseAudio; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA. -***/ - -#include - -int pa_autospawn_lock_init(void); -int pa_autospawn_lock_acquire(pa_bool_t block); -void pa_autospawn_lock_release(void); -void pa_autospawn_lock_done(pa_bool_t after_fork); - -#endif diff --git a/src/pulsecore/lock-autospawn.c b/src/pulsecore/lock-autospawn.c new file mode 100644 index 00000000..d36b669e --- /dev/null +++ b/src/pulsecore/lock-autospawn.c @@ -0,0 +1,330 @@ +/*** + This file is part of PulseAudio. + + Copyright 2008 Lennart Poettering + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include "lock-autospawn.h" + +/* So, why do we have this complex code here with threads and pipes + * and stuff? For two reasons: POSIX file locks are per-process, not + * per-file descriptor. That means that two contexts within the same + * process that try to create the autospawn lock might end up assuming + * they both managed to lock the file. And then, POSIX locking + * operations are synchronous. If two contexts run from the same event + * loop it must be made sure that they do not block each other, but + * that the locking operation can happen asynchronously. */ + +#define AUTOSPAWN_LOCK "autospawn.lock" + +static pa_mutex *mutex; + +static unsigned n_ref = 0; +static int lock_fd = -1; +static pa_mutex *lock_fd_mutex = NULL; +static pa_bool_t taken = FALSE; +static pa_thread *thread; +static int pipe_fd[2] = { -1, -1 }; + +static void destroy_mutex(void) PA_GCC_DESTRUCTOR; + +static int ref(void) { + + if (n_ref > 0) { + + pa_assert(pipe_fd[0] >= 0); + pa_assert(pipe_fd[1] >= 0); + + n_ref++; + + return 0; + } + + pa_assert(lock_fd < 0); + pa_assert(!lock_fd_mutex); + pa_assert(!taken); + pa_assert(!thread); + pa_assert(pipe_fd[0] < 0); + pa_assert(pipe_fd[1] < 0); + + if (pipe(pipe_fd) < 0) + return -1; + + lock_fd_mutex = pa_mutex_new(FALSE, FALSE); + + pa_make_fd_cloexec(pipe_fd[0]); + pa_make_fd_cloexec(pipe_fd[1]); + + pa_make_fd_nonblock(pipe_fd[1]); + pa_make_fd_nonblock(pipe_fd[0]); + + n_ref = 1; + return 0; +} + +static void unref(pa_bool_t after_fork) { + + pa_assert(n_ref > 0); + pa_assert(pipe_fd[0] >= 0); + pa_assert(pipe_fd[1] >= 0); + pa_assert(lock_fd_mutex); + + n_ref--; + + if (n_ref > 0) + return; + + pa_assert(!taken); + + if (thread) { + pa_thread_free(thread); + thread = NULL; + } + + pa_mutex_lock(lock_fd_mutex); + if (lock_fd >= 0) { + + if (after_fork) + pa_close(lock_fd); + else { + char *lf; + + if (!(lf = pa_runtime_path(AUTOSPAWN_LOCK))) + pa_log_warn(_("Cannot access autospawn lock.")); + + pa_unlock_lockfile(lf, lock_fd); + pa_xfree(lf); + + lock_fd = -1; + } + } + pa_mutex_unlock(lock_fd_mutex); + + pa_mutex_free(lock_fd_mutex); + lock_fd_mutex = NULL; + + pa_close(pipe_fd[0]); + pa_close(pipe_fd[1]); + pipe_fd[0] = pipe_fd[1] = -1; +} + +static void ping(void) { + ssize_t s; + + pa_assert(pipe_fd[1] >= 0); + + for (;;) { + char x = 'x'; + + if ((s = write(pipe_fd[1], &x, 1)) == 1) + break; + + pa_assert(s < 0); + + if (errno == EAGAIN) + break; + + pa_assert(errno == EINTR); + } +} + +static void wait_for_ping(void) { + ssize_t s; + char x; + struct pollfd pfd; + int k; + + pa_assert(pipe_fd[0] >= 0); + + memset(&pfd, 0, sizeof(pfd)); + pfd.fd = pipe_fd[0]; + pfd.events = POLLIN; + + if ((k = poll(&pfd, 1, -1)) != 1) { + pa_assert(k < 0); + pa_assert(errno == EINTR); + } else if ((s = read(pipe_fd[0], &x, 1)) != 1) { + pa_assert(s < 0); + pa_assert(errno == EAGAIN); + } +} + +static void empty_pipe(void) { + char x[16]; + ssize_t s; + + pa_assert(pipe_fd[0] >= 0); + + if ((s = read(pipe_fd[0], &x, sizeof(x))) < 1) { + pa_assert(s < 0); + pa_assert(errno == EAGAIN); + } +} + +static void thread_func(void *u) { + int fd; + char *lf; + sigset_t fullset; + + /* No signals in this thread please */ + sigfillset(&fullset); + pthread_sigmask(SIG_BLOCK, &fullset, NULL); + + if (!(lf = pa_runtime_path(AUTOSPAWN_LOCK))) { + pa_log_warn(_("Cannot access autospawn lock.")); + goto finish; + } + + if ((fd = pa_lock_lockfile(lf)) < 0) + goto finish; + + pa_mutex_lock(lock_fd_mutex); + pa_assert(lock_fd < 0); + lock_fd = fd; + pa_mutex_unlock(lock_fd_mutex); + +finish: + pa_xfree(lf); + + ping(); +} + +static int start_thread(void) { + + if (!thread) + if (!(thread = pa_thread_new(thread_func, NULL))) + return -1; + + return 0; +} + +static void create_mutex(void) { + PA_ONCE_BEGIN { + mutex = pa_mutex_new(FALSE, FALSE); + } PA_ONCE_END; +} + +static void destroy_mutex(void) { + + if (mutex) + pa_mutex_free(mutex); +} + + +int pa_autospawn_lock_init(void) { + int ret = -1; + + create_mutex(); + pa_mutex_lock(mutex); + + if (ref() < 0) + ret = -1; + else + ret = pipe_fd[0]; + + pa_mutex_unlock(mutex); + + return ret; +} + +int pa_autospawn_lock_acquire(pa_bool_t block) { + int ret = -1; + + create_mutex(); + pa_mutex_lock(mutex); + pa_assert(n_ref >= 1); + + pa_mutex_lock(lock_fd_mutex); + + for (;;) { + + empty_pipe(); + + if (lock_fd >= 0 && !taken) { + taken = TRUE; + ret = 1; + break; + } + + if (lock_fd < 0) + if (start_thread() < 0) + break; + + if (!block) { + ret = 0; + break; + } + + pa_mutex_unlock(lock_fd_mutex); + pa_mutex_unlock(mutex); + + wait_for_ping(); + + pa_mutex_lock(mutex); + pa_mutex_lock(lock_fd_mutex); + } + + pa_mutex_unlock(lock_fd_mutex); + + pa_mutex_unlock(mutex); + + return ret; +} + +void pa_autospawn_lock_release(void) { + + create_mutex(); + pa_mutex_lock(mutex); + pa_assert(n_ref >= 1); + + pa_assert(taken); + taken = FALSE; + + ping(); + + pa_mutex_unlock(mutex); +} + +void pa_autospawn_lock_done(pa_bool_t after_fork) { + + create_mutex(); + pa_mutex_lock(mutex); + pa_assert(n_ref >= 1); + + unref(after_fork); + + pa_mutex_unlock(mutex); +} diff --git a/src/pulsecore/lock-autospawn.h b/src/pulsecore/lock-autospawn.h new file mode 100644 index 00000000..c04c4bd1 --- /dev/null +++ b/src/pulsecore/lock-autospawn.h @@ -0,0 +1,32 @@ +#ifndef foopulselockautospawnhfoo +#define foopulselockautospawnhfoo + +/*** + This file is part of PulseAudio. + + Copyright 2008 Lennart Poettering + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include + +int pa_autospawn_lock_init(void); +int pa_autospawn_lock_acquire(pa_bool_t block); +void pa_autospawn_lock_release(void); +void pa_autospawn_lock_done(pa_bool_t after_fork); + +#endif diff --git a/src/tests/lock-autospawn-test.c b/src/tests/lock-autospawn-test.c index cb3dc87c..80cfda6a 100644 --- a/src/tests/lock-autospawn-test.c +++ b/src/tests/lock-autospawn-test.c @@ -28,7 +28,7 @@ #include #include -#include +#include #include static void thread_func(void*k) { -- cgit