X-Git-Url: https://code.delx.au/pulseaudio/blobdiff_plain/1e12e0ee8dfdda1632b9c082aba6fc1956813a5b..eca082a93f2619cfa10733947a81fa779cb49573:/src/modules/gconf/module-gconf.c diff --git a/src/modules/gconf/module-gconf.c b/src/modules/gconf/module-gconf.c index cbe17d20..38857461 100644 --- a/src/modules/gconf/module-gconf.c +++ b/src/modules/gconf/module-gconf.c @@ -1,5 +1,3 @@ -/* $Id$ */ - /*** This file is part of PulseAudio. @@ -7,7 +5,7 @@ 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, + 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 @@ -25,7 +23,6 @@ #include #endif -#include #include #include #include @@ -33,36 +30,27 @@ #include #include #include -#include - -#ifdef HAVE_SYS_PRCTL_H -#include -#endif -#ifdef HAVE_SYS_RESOURCE_H -#include -#endif +#include #include #include -#include #include #include #include -#include #include +#include #include "module-gconf-symdef.h" -PA_MODULE_AUTHOR("Lennart Poettering") -PA_MODULE_DESCRIPTION("GConf Adapter") -PA_MODULE_VERSION(PACKAGE_VERSION) -PA_MODULE_USAGE("") +PA_MODULE_AUTHOR("Lennart Poettering"); +PA_MODULE_DESCRIPTION("GConf Adapter"); +PA_MODULE_VERSION(PACKAGE_VERSION); +PA_MODULE_LOAD_ONCE(true); #define MAX_MODULES 10 #define BUF_MAX 2048 -/* #undef PA_GCONF_HELPER */ -/* #define PA_GCONF_HELPER "/home/lennart/projects/pulseaudio/src/gconf-helper" */ +struct userdata; struct module_item { char *name; @@ -71,6 +59,7 @@ struct module_item { }; struct module_info { + struct userdata *userdata; char *name; struct module_item items[MAX_MODULES]; @@ -95,7 +84,7 @@ struct userdata { static int fill_buf(struct userdata *u) { ssize_t r; - assert(u); + pa_assert(u); if (u->buf_fill >= BUF_MAX) { pa_log("read buffer overflow"); @@ -105,34 +94,34 @@ static int fill_buf(struct userdata *u) { if ((r = pa_read(u->fd, u->buf + u->buf_fill, BUF_MAX - u->buf_fill, &u->fd_type)) <= 0) return -1; - u->buf_fill += r; + u->buf_fill += (size_t) r; return 0; } static int read_byte(struct userdata *u) { int ret; - assert(u); + pa_assert(u); if (u->buf_fill < 1) if (fill_buf(u) < 0) return -1; ret = u->buf[0]; - assert(u->buf_fill > 0); + pa_assert(u->buf_fill > 0); u->buf_fill--; memmove(u->buf, u->buf+1, u->buf_fill); return ret; } static char *read_string(struct userdata *u) { - assert(u); + pa_assert(u); for (;;) { char *e; if ((e = memchr(u->buf, 0, u->buf_fill))) { char *ret = pa_xstrdup(u->buf); - u->buf_fill -= e - u->buf +1; + u->buf_fill -= (size_t) (e - u->buf +1); memmove(u->buf, e+1, u->buf_fill); return ret; } @@ -142,56 +131,59 @@ static char *read_string(struct userdata *u) { } } -static void unload_one_module(struct userdata *u, struct module_info*m, unsigned i) { - assert(u); - assert(m); - assert(i < m->n_items); +static void unload_one_module(struct module_info *m, unsigned i) { + struct userdata *u; + + pa_assert(m); + pa_assert(i < m->n_items); + + u = m->userdata; if (m->items[i].index == PA_INVALID_INDEX) return; pa_log_debug("Unloading module #%i", m->items[i].index); - pa_module_unload_by_index(u->core, m->items[i].index); + pa_module_unload_by_index(u->core, m->items[i].index, true); m->items[i].index = PA_INVALID_INDEX; pa_xfree(m->items[i].name); pa_xfree(m->items[i].args); m->items[i].name = m->items[i].args = NULL; } -static void unload_all_modules(struct userdata *u, struct module_info*m) { +static void unload_all_modules(struct module_info *m) { unsigned i; - assert(u); - assert(m); + pa_assert(m); for (i = 0; i < m->n_items; i++) - unload_one_module(u, m, i); + unload_one_module(m, i); m->n_items = 0; } static void load_module( - struct userdata *u, struct module_info *m, - int i, + unsigned i, const char *name, const char *args, - int is_new) { + bool is_new) { + struct userdata *u; pa_module *mod; - assert(u); - assert(m); - assert(name); - assert(args); + pa_assert(m); + pa_assert(name); + pa_assert(args); + + u = m->userdata; if (!is_new) { if (m->items[i].index != PA_INVALID_INDEX && - strcmp(m->items[i].name, name) == 0 && - strcmp(m->items[i].args, args) == 0) + pa_streq(m->items[i].name, name) && + pa_streq(m->items[i].args, args)) return; - unload_one_module(u, m, i); + unload_one_module(m, i); } pa_log_debug("Loading module '%s' with args '%s' due to GConf configuration.", name, args); @@ -208,14 +200,12 @@ static void load_module( m->items[i].index = mod->index; } -static void module_info_free(void *p, void *userdata) { +static void module_info_free(void *p) { struct module_info *m = p; - struct userdata *u = userdata; - assert(m); - assert(u); + pa_assert(m); - unload_all_modules(u, m); + unload_all_modules(m); pa_xfree(m->name); pa_xfree(m); } @@ -225,8 +215,11 @@ static int handle_event(struct userdata *u) { int ret = 0; do { - if ((opcode = read_byte(u)) < 0) + if ((opcode = read_byte(u)) < 0) { + if (errno == EINTR || errno == EAGAIN) + break; goto fail; + } switch (opcode) { case '!': @@ -244,6 +237,7 @@ static int handle_event(struct userdata *u) { if (!(m = pa_hashmap_get(u->module_infos, name))) { m = pa_xnew(struct module_info, 1); + m->userdata = u; m->name = name; m->n_items = 0; pa_hashmap_put(u->module_infos, m->name, m); @@ -271,7 +265,7 @@ static int handle_event(struct userdata *u) { goto fail; } - load_module(u, m, i, module, args, i >= m->n_items); + load_module(m, i, module, args, i >= m->n_items); i++; @@ -281,7 +275,7 @@ static int handle_event(struct userdata *u) { /* Unload all removed modules */ for (j = i; j < m->n_items; j++) - unload_one_module(u, m, j); + unload_one_module(m, j); m->n_items = i; @@ -295,11 +289,7 @@ static int handle_event(struct userdata *u) { if (!(name = read_string(u))) goto fail; - if ((m = pa_hashmap_get(u->module_infos, name))) { - pa_hashmap_remove(u->module_infos, name); - module_info_free(m, u); - } - + pa_hashmap_remove_and_free(u->module_infos, name); pa_xfree(name); break; @@ -330,109 +320,34 @@ static void io_event_cb( u->io_event = NULL; } - pa_module_unload_request(u->module); - } -} - -static int start_client(const char *n, pid_t *pid) { - pid_t child; - int pipe_fds[2] = { -1, -1 }; - - if (pipe(pipe_fds) < 0) { - pa_log("pipe() failed: %s", pa_cstrerror(errno)); - goto fail; - } - - if ((child = fork()) == (pid_t) -1) { - pa_log("fork() failed: %s", pa_cstrerror(errno)); - goto fail; - } else if (child != 0) { - - /* Parent */ - close(pipe_fds[1]); - - if (pid) - *pid = child; - - return pipe_fds[0]; - } else { - int max_fd, i; - - /* child */ - - close(pipe_fds[0]); - dup2(pipe_fds[1], 1); - - if (pipe_fds[1] != 1) - close(pipe_fds[1]); - - close(0); - open("/dev/null", O_RDONLY); - - close(2); - open("/dev/null", O_WRONLY); - - max_fd = 1024; - -#ifdef HAVE_SYS_RESOURCE_H - { - struct rlimit r; - if (getrlimit(RLIMIT_NOFILE, &r) == 0) - max_fd = r.rlim_max; - } -#endif - - for (i = 3; i < max_fd; i++) - close(i); - -#ifdef PR_SET_PDEATHSIG - /* On Linux we can use PR_SET_PDEATHSIG to have the helper - process killed when the daemon dies abnormally. On non-Linux - machines the client will die as soon as it writes data to - stdout again (SIGPIPE) */ - - prctl(PR_SET_PDEATHSIG, SIGTERM, 0, 0, 0); -#endif - -#ifdef SIGPIPE - /* Make sure that SIGPIPE kills the child process */ - signal(SIGPIPE, SIG_DFL); -#endif - - execl(n, n, NULL); - _exit(1); + pa_module_unload_request(u->module, true); } - -fail: - if (pipe_fds[0] >= 0) - close(pipe_fds[0]); - - if (pipe_fds[1] >= 0) - close(pipe_fds[1]); - - return -1; } -int pa__init(pa_core *c, pa_module*m) { +int pa__init(pa_module*m) { struct userdata *u; int r; u = pa_xnew(struct userdata, 1); - u->core = c; + u->core = m->core; u->module = m; m->userdata = u; - u->module_infos = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); + u->module_infos = pa_hashmap_new_full(pa_idxset_string_hash_func, pa_idxset_string_compare_func, NULL, (pa_free_cb_t) module_info_free); u->pid = (pid_t) -1; u->fd = -1; u->fd_type = 0; u->io_event = NULL; u->buf_fill = 0; - if ((u->fd = start_client(PA_GCONF_HELPER, &u->pid)) < 0) + if ((u->fd = pa_start_child_for_read( +#if defined(__linux__) && !defined(__OPTIMIZE__) + pa_run_from_build_tree() ? PA_BUILDDIR "/gconf-helper" : +#endif + PA_GCONF_HELPER, NULL, &u->pid)) < 0) goto fail; - u->io_event = c->mainloop->io_new( - c->mainloop, + u->io_event = m->core->mainloop->io_new( + m->core->mainloop, u->fd, PA_IO_EVENT_INPUT, io_event_cb, @@ -449,33 +364,40 @@ int pa__init(pa_core *c, pa_module*m) { return 0; fail: - pa__done(c, m); + pa__done(m); return -1; } -void pa__done(pa_core *c, pa_module*m) { +void pa__done(pa_module*m) { struct userdata *u; - assert(c); - assert(m); + pa_assert(m); if (!(u = m->userdata)) return; - if (u->io_event) - c->mainloop->io_free(u->io_event); - - if (u->fd >= 0) - close(u->fd); - if (u->pid != (pid_t) -1) { kill(u->pid, SIGTERM); - waitpid(u->pid, NULL, 0); + + for (;;) { + if (waitpid(u->pid, NULL, 0) >= 0) + break; + + if (errno != EINTR) { + pa_log("waitpid() failed: %s", pa_cstrerror(errno)); + break; + } + } } + if (u->io_event) + m->core->mainloop->io_free(u->io_event); + + if (u->fd >= 0) + pa_close(u->fd); + if (u->module_infos) - pa_hashmap_free(u->module_infos, module_info_free, u); + pa_hashmap_free(u->module_infos); pa_xfree(u); } -