From cc1d8213d6a58b0022017f8d231a346387aab507 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 26 Jul 2006 17:36:14 +0000 Subject: add new module "module-gconf" which reads configuration information from gconf. this will be used in my upcoming paconf module git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1150 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/gconf/module-gconf.c | 386 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 386 insertions(+) create mode 100644 src/modules/gconf/module-gconf.c (limited to 'src/modules/gconf/module-gconf.c') diff --git a/src/modules/gconf/module-gconf.c b/src/modules/gconf/module-gconf.c new file mode 100644 index 00000000..30e6292e --- /dev/null +++ b/src/modules/gconf/module-gconf.c @@ -0,0 +1,386 @@ +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + 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 +#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("") + +#define MAX_MODULES 10 +#define BUF_MAX 2048 + +#undef PA_GCONF_HELPER +#define PA_GCONF_HELPER "/home/lennart/projects/pulseaudio/src/gconf-helper" + +struct module_info { + char *name; + + unsigned n_indexes; + uint32_t indexes[MAX_MODULES]; +}; + +struct userdata { + pa_core *core; + pa_module *module; + + pa_hashmap *module_infos; + + pid_t pid; + + int fd; + int fd_type; + pa_io_event *io_event; + + char buf[BUF_MAX]; + size_t buf_fill; +}; + +static int fill_buf(struct userdata *u) { + ssize_t r; + assert(u); + + if (u->buf_fill >= BUF_MAX) { + pa_log(__FILE__": read buffer overflow"); + return -1; + } + + 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; + return 0; +} + +static int read_byte(struct userdata *u) { + int ret; + assert(u); + + if (u->buf_fill < 1) + if (fill_buf(u) < 0) + return -1; + + ret = u->buf[0]; + 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); + + 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; + memmove(u->buf, e+1, u->buf_fill); + return ret; + } + + if (fill_buf(u) < 0) + return NULL; + } +} + +static void unload_modules(struct userdata *u, struct module_info*m) { + unsigned i; + + assert(u); + assert(m); + + for (i = 0; i < m->n_indexes; i++) { + pa_log_debug(__FILE__": Unloading module #%i", m->indexes[i]); + pa_module_unload_by_index(u->core, m->indexes[i]); + } + + m->n_indexes = 0; +} + +static void load_module( + struct userdata *u, + struct module_info *m, + const char *module, + const char *args) { + + pa_module *mod; + + assert(u); + assert(m); + assert(module); + + assert(m->n_indexes < MAX_MODULES); + + pa_log_debug(__FILE__": Loading module '%s' with args '%s' due to GConf configuration.", module, args); + + if (!(mod = pa_module_load(u->core, module, args))) { + pa_log(__FILE__": pa_module_load() failed"); + return; + } + + m->indexes[m->n_indexes++] = mod->index; +} + +static void module_info_free(void *p, void *userdata) { + struct module_info *m = p; + struct userdata *u = userdata; + + assert(m); + assert(u); + + unload_modules(u, m); + pa_xfree(m->name); + pa_xfree(m); +} + +static int handle_event(struct userdata *u) { + int opcode; + int ret = 0; + + do { + if ((opcode = read_byte(u)) < 0) + goto fail; + + switch (opcode) { + case '!': + /* The helper tool is now initialized */ + ret = 1; + break; + + case '+': { + char *name; + struct module_info *m; + + if (!(name = read_string(u))) + goto fail; + + if ((m = pa_hashmap_get(u->module_infos, name))) { + unload_modules(u, m); + } else { + m = pa_xnew(struct module_info, 1); + m->name = pa_xstrdup(name); + m->n_indexes = 0; + pa_hashmap_put(u->module_infos, m->name, m); + } + + while (m->n_indexes < MAX_MODULES) { + char *module, *args; + + if (!(module = read_string(u))) { + pa_xfree(name); + goto fail; + } + + if (!*module) { + pa_xfree(module); + break; + } + + if (!(args = read_string(u))) { + pa_xfree(name); + pa_xfree(module); + goto fail; + } + + load_module(u, m, module, args); + + pa_xfree(module); + pa_xfree(args); + } + + pa_xfree(name); + + break; + } + + case '-': { + char *name; + struct module_info *m; + + 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_xfree(name); + + break; + } + } + } while (u->buf_fill > 0 && ret == 0); + + return ret; + +fail: + pa_log(__FILE__": Unable to read or parse data from client."); + return -1; +} + +static void io_event_cb( + pa_mainloop_api*a, + pa_io_event* e, + int fd, + pa_io_event_flags_t events, + void *userdata) { + + struct userdata *u = userdata; + + handle_event(u); +} + +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(__FILE__": pipe() failed: %s", pa_cstrerror(errno)); + goto fail; + } + + if ((child = fork()) == (pid_t) -1) { + pa_log(__FILE__": 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 { + + /* child */ + + close(pipe_fds[0]); + dup2(pipe_fds[1], 1); + + if (pipe_fds[1] != 1) + close(pipe_fds[1]); + + execl(n, n, NULL); + _exit(1); + } + +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) { + struct userdata *u; + int r; + + u = pa_xnew(struct userdata, 1); + u->core = c; + u->module = m; + u->module_infos = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); + 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) + goto fail; + + u->io_event = c->mainloop->io_new( + c->mainloop, + u->fd, + PA_IO_EVENT_INPUT, + io_event_cb, + u); + + do { + if ((r = handle_event(u)) < 0) + goto fail; + + /* Read until the client signalled us that it is ready with + * initialization */ + } while (r != 1); + + return 0; + +fail: + pa__done(c, m); + return -1; +} + +void pa__done(pa_core *c, pa_module*m) { + struct userdata *u; + + assert(c); + 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); + } + + if (u->module_infos) + pa_hashmap_free(u->module_infos, module_info_free, u); + + pa_xfree(u); +} + -- cgit From b2ad9a9753d9d5e69192a620b714f7e32a31e574 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 26 Jul 2006 18:28:31 +0000 Subject: add some protection that the gconf helper process will be killed when the daemon process dies. make sure the gconf helper process doesn't keep open file descriptors belonging to the daemon; if gconf helper path git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1152 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/gconf/module-gconf.c | 58 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 54 insertions(+), 4 deletions(-) (limited to 'src/modules/gconf/module-gconf.c') diff --git a/src/modules/gconf/module-gconf.c b/src/modules/gconf/module-gconf.c index 30e6292e..c6f83f6d 100644 --- a/src/modules/gconf/module-gconf.c +++ b/src/modules/gconf/module-gconf.c @@ -31,6 +31,14 @@ #include #include #include +#include + +#ifdef HAVE_SYS_PRCTL_H +#include +#endif +#ifdef HAVE_SYS_RESOURCE_H +#include +#endif #include #include @@ -51,8 +59,8 @@ PA_MODULE_USAGE("") #define MAX_MODULES 10 #define BUF_MAX 2048 -#undef PA_GCONF_HELPER -#define PA_GCONF_HELPER "/home/lennart/projects/pulseaudio/src/gconf-helper" +/* #undef PA_GCONF_HELPER */ +/* #define PA_GCONF_HELPER "/home/lennart/projects/pulseaudio/src/gconf-helper" */ struct module_info { char *name; @@ -271,7 +279,15 @@ static void io_event_cb( struct userdata *u = userdata; - handle_event(u); + if (handle_event(u) < 0) { + + if (u->io_event) { + u->core->mainloop->io_free(u->io_event); + u->io_event = NULL; + } + + pa_module_unload_request(u->module); + } } static int start_client(const char *n, pid_t *pid) { @@ -296,7 +312,8 @@ static int start_client(const char *n, pid_t *pid) { return pipe_fds[0]; } else { - + int max_fd, i; + /* child */ close(pipe_fds[0]); @@ -305,6 +322,39 @@ static int start_client(const char *n, pid_t *pid) { 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); } -- cgit From fec7e9bec70364996a857b5f4e2cee01299ea59c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 27 Jul 2006 16:51:20 +0000 Subject: if possible do not unload already loaded modules when the gconf settings change. instead try to reuse already loaded modules as much as possible git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1157 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/gconf/module-gconf.c | 100 +++++++++++++++++++++++++++------------ 1 file changed, 71 insertions(+), 29 deletions(-) (limited to 'src/modules/gconf/module-gconf.c') diff --git a/src/modules/gconf/module-gconf.c b/src/modules/gconf/module-gconf.c index c6f83f6d..d524346c 100644 --- a/src/modules/gconf/module-gconf.c +++ b/src/modules/gconf/module-gconf.c @@ -62,11 +62,17 @@ PA_MODULE_USAGE("") /* #undef PA_GCONF_HELPER */ /* #define PA_GCONF_HELPER "/home/lennart/projects/pulseaudio/src/gconf-helper" */ +struct module_item { + char *name; + char *args; + uint32_t index; +}; + struct module_info { char *name; - - unsigned n_indexes; - uint32_t indexes[MAX_MODULES]; + + struct module_item items[MAX_MODULES]; + unsigned n_items; }; struct userdata { @@ -134,42 +140,70 @@ static char *read_string(struct userdata *u) { } } -static void unload_modules(struct userdata *u, struct module_info*m) { +static void unload_one_module(struct userdata *u, struct module_info*m, unsigned i) { + assert(u); + assert(m); + assert(i < m->n_items); + + if (m->items[i].index == PA_INVALID_INDEX) + return; + + pa_log_debug(__FILE__": Unloading module #%i", m->items[i].index); + pa_module_unload_by_index(u->core, m->items[i].index); + 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) { unsigned i; assert(u); assert(m); - for (i = 0; i < m->n_indexes; i++) { - pa_log_debug(__FILE__": Unloading module #%i", m->indexes[i]); - pa_module_unload_by_index(u->core, m->indexes[i]); - } + for (i = 0; i < m->n_items; i++) + unload_one_module(u, m, i); - m->n_indexes = 0; + m->n_items = 0; } static void load_module( struct userdata *u, struct module_info *m, - const char *module, - const char *args) { + int i, + const char *name, + const char *args, + int is_new) { pa_module *mod; assert(u); assert(m); - assert(module); + assert(name); + assert(args); + + 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) + return; - assert(m->n_indexes < MAX_MODULES); + unload_one_module(u, m, i); + } + + pa_log_debug(__FILE__": Loading module '%s' with args '%s' due to GConf configuration.", name, args); - pa_log_debug(__FILE__": Loading module '%s' with args '%s' due to GConf configuration.", module, args); + m->items[i].name = pa_xstrdup(name); + m->items[i].args = pa_xstrdup(args); + m->items[i].index = PA_INVALID_INDEX; - if (!(mod = pa_module_load(u->core, module, args))) { + if (!(mod = pa_module_load(u->core, name, args))) { pa_log(__FILE__": pa_module_load() failed"); return; } - m->indexes[m->n_indexes++] = mod->index; + m->items[i].index = mod->index; } static void module_info_free(void *p, void *userdata) { @@ -179,7 +213,7 @@ static void module_info_free(void *p, void *userdata) { assert(m); assert(u); - unload_modules(u, m); + unload_all_modules(u, m); pa_xfree(m->name); pa_xfree(m); } @@ -201,24 +235,25 @@ static int handle_event(struct userdata *u) { case '+': { char *name; struct module_info *m; + unsigned i, j; if (!(name = read_string(u))) goto fail; - if ((m = pa_hashmap_get(u->module_infos, name))) { - unload_modules(u, m); - } else { + if (!(m = pa_hashmap_get(u->module_infos, name))) { m = pa_xnew(struct module_info, 1); - m->name = pa_xstrdup(name); - m->n_indexes = 0; + m->name = name; + m->n_items = 0; pa_hashmap_put(u->module_infos, m->name, m); - } - - while (m->n_indexes < MAX_MODULES) { + } else + pa_xfree(name); + + i = 0; + while (i < MAX_MODULES) { char *module, *args; if (!(module = read_string(u))) { - pa_xfree(name); + if (i > m->n_items) m->n_items = i; goto fail; } @@ -228,18 +263,25 @@ static int handle_event(struct userdata *u) { } if (!(args = read_string(u))) { - pa_xfree(name); pa_xfree(module); + + if (i > m->n_items) m->n_items = i; goto fail; } - load_module(u, m, module, args); + load_module(u, m, i, module, args, i >= m->n_items); + + i++; pa_xfree(module); pa_xfree(args); } - pa_xfree(name); + /* Unload all removed modules */ + for (j = i; j < m->n_items; j++) + unload_one_module(u, m, j); + + m->n_items = i; break; } -- cgit From d7ee1bcf758241d744002e3aea982295ce9e9247 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 29 Jul 2006 17:42:25 +0000 Subject: fix module-gconf initialization git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1172 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/gconf/module-gconf.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src/modules/gconf/module-gconf.c') diff --git a/src/modules/gconf/module-gconf.c b/src/modules/gconf/module-gconf.c index d524346c..a61295e0 100644 --- a/src/modules/gconf/module-gconf.c +++ b/src/modules/gconf/module-gconf.c @@ -418,6 +418,7 @@ int pa__init(pa_core *c, pa_module*m) { u = pa_xnew(struct userdata, 1); u->core = c; u->module = m; + m->userdata = u; u->module_infos = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); u->pid = (pid_t) -1; u->fd = -1; -- cgit From e385d93e5aad6a6fce754c00c804ff1d6a6746d4 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 18 Aug 2006 21:38:40 +0000 Subject: remove all occurences of pa_logXXX(__FILE__": and replace them by pa_logXXX(" git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1272 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/gconf/module-gconf.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'src/modules/gconf/module-gconf.c') diff --git a/src/modules/gconf/module-gconf.c b/src/modules/gconf/module-gconf.c index a61295e0..d9f649fd 100644 --- a/src/modules/gconf/module-gconf.c +++ b/src/modules/gconf/module-gconf.c @@ -96,7 +96,7 @@ static int fill_buf(struct userdata *u) { assert(u); if (u->buf_fill >= BUF_MAX) { - pa_log(__FILE__": read buffer overflow"); + pa_log("read buffer overflow"); return -1; } @@ -148,7 +148,7 @@ static void unload_one_module(struct userdata *u, struct module_info*m, unsigned if (m->items[i].index == PA_INVALID_INDEX) return; - pa_log_debug(__FILE__": Unloading module #%i", m->items[i].index); + pa_log_debug("Unloading module #%i", m->items[i].index); pa_module_unload_by_index(u->core, m->items[i].index); m->items[i].index = PA_INVALID_INDEX; pa_xfree(m->items[i].name); @@ -192,14 +192,14 @@ static void load_module( unload_one_module(u, m, i); } - pa_log_debug(__FILE__": Loading module '%s' with args '%s' due to GConf configuration.", name, args); + pa_log_debug("Loading module '%s' with args '%s' due to GConf configuration.", name, args); m->items[i].name = pa_xstrdup(name); m->items[i].args = pa_xstrdup(args); m->items[i].index = PA_INVALID_INDEX; if (!(mod = pa_module_load(u->core, name, args))) { - pa_log(__FILE__": pa_module_load() failed"); + pa_log("pa_module_load() failed"); return; } @@ -308,7 +308,7 @@ static int handle_event(struct userdata *u) { return ret; fail: - pa_log(__FILE__": Unable to read or parse data from client."); + pa_log("Unable to read or parse data from client."); return -1; } @@ -337,12 +337,12 @@ static int start_client(const char *n, pid_t *pid) { int pipe_fds[2] = { -1, -1 }; if (pipe(pipe_fds) < 0) { - pa_log(__FILE__": pipe() failed: %s", pa_cstrerror(errno)); + pa_log("pipe() failed: %s", pa_cstrerror(errno)); goto fail; } if ((child = fork()) == (pid_t) -1) { - pa_log(__FILE__": fork() failed: %s", pa_cstrerror(errno)); + pa_log("fork() failed: %s", pa_cstrerror(errno)); goto fail; } else if (child != 0) { -- cgit From 06211b7c8fd329137ae9003818543912a87d9898 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 13 Feb 2007 15:35:19 +0000 Subject: Add copyright notices to all relevant files. (based on svn log) git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1426 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/gconf/module-gconf.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/modules/gconf/module-gconf.c') diff --git a/src/modules/gconf/module-gconf.c b/src/modules/gconf/module-gconf.c index d9f649fd..df7b1643 100644 --- a/src/modules/gconf/module-gconf.c +++ b/src/modules/gconf/module-gconf.c @@ -2,6 +2,8 @@ /*** This file is part of PulseAudio. + + Copyright 2006 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 -- cgit From 1e12e0ee8dfdda1632b9c082aba6fc1956813a5b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 29 May 2007 17:24:48 +0000 Subject: Kill spaces on EOL git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1465 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/gconf/module-gconf.c | 62 ++++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 31 deletions(-) (limited to 'src/modules/gconf/module-gconf.c') diff --git a/src/modules/gconf/module-gconf.c b/src/modules/gconf/module-gconf.c index df7b1643..cbe17d20 100644 --- a/src/modules/gconf/module-gconf.c +++ b/src/modules/gconf/module-gconf.c @@ -4,17 +4,17 @@ This file is part of PulseAudio. Copyright 2006 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 @@ -80,7 +80,7 @@ struct module_info { struct userdata { pa_core *core; pa_module *module; - + pa_hashmap *module_infos; pid_t pid; @@ -129,7 +129,7 @@ static char *read_string(struct userdata *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; @@ -149,7 +149,7 @@ static void unload_one_module(struct userdata *u, struct module_info*m, unsigned 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); m->items[i].index = PA_INVALID_INDEX; @@ -160,7 +160,7 @@ static void unload_one_module(struct userdata *u, struct module_info*m, unsigned static void unload_all_modules(struct userdata *u, struct module_info*m) { unsigned i; - + assert(u); assert(m); @@ -179,7 +179,7 @@ static void load_module( int is_new) { pa_module *mod; - + assert(u); assert(m); assert(name); @@ -193,18 +193,18 @@ static void load_module( unload_one_module(u, m, i); } - + pa_log_debug("Loading module '%s' with args '%s' due to GConf configuration.", name, args); m->items[i].name = pa_xstrdup(name); m->items[i].args = pa_xstrdup(args); m->items[i].index = PA_INVALID_INDEX; - + if (!(mod = pa_module_load(u->core, name, args))) { pa_log("pa_module_load() failed"); return; } - + m->items[i].index = mod->index; } @@ -227,18 +227,18 @@ static int handle_event(struct userdata *u) { do { if ((opcode = read_byte(u)) < 0) goto fail; - + switch (opcode) { case '!': /* The helper tool is now initialized */ ret = 1; break; - + case '+': { char *name; struct module_info *m; unsigned i, j; - + if (!(name = read_string(u))) goto fail; @@ -282,16 +282,16 @@ 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); - + m->n_items = i; - + break; } - + case '-': { char *name; struct module_info *m; - + if (!(name = read_string(u))) goto fail; @@ -301,7 +301,7 @@ static int handle_event(struct userdata *u) { } pa_xfree(name); - + break; } } @@ -324,12 +324,12 @@ static void io_event_cb( struct userdata *u = userdata; if (handle_event(u) < 0) { - + if (u->io_event) { u->core->mainloop->io_free(u->io_event); u->io_event = NULL; } - + pa_module_unload_request(u->module); } } @@ -342,7 +342,7 @@ static int start_client(const char *n, pid_t *pid) { 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; @@ -357,7 +357,7 @@ static int start_client(const char *n, pid_t *pid) { return pipe_fds[0]; } else { int max_fd, i; - + /* child */ close(pipe_fds[0]); @@ -373,7 +373,7 @@ static int start_client(const char *n, pid_t *pid) { open("/dev/null", O_WRONLY); max_fd = 1024; - + #ifdef HAVE_SYS_RESOURCE_H { struct rlimit r; @@ -381,7 +381,7 @@ static int start_client(const char *n, pid_t *pid) { max_fd = r.rlim_max; } #endif - + for (i = 3; i < max_fd; i++) close(i); @@ -402,14 +402,14 @@ static int start_client(const char *n, pid_t *pid) { execl(n, n, NULL); _exit(1); } - + fail: if (pipe_fds[0] >= 0) close(pipe_fds[0]); if (pipe_fds[1] >= 0) close(pipe_fds[1]); - + return -1; } @@ -427,17 +427,17 @@ int pa__init(pa_core *c, pa_module*m) { u->fd_type = 0; u->io_event = NULL; u->buf_fill = 0; - + if ((u->fd = start_client(PA_GCONF_HELPER, &u->pid)) < 0) goto fail; - + u->io_event = c->mainloop->io_new( c->mainloop, u->fd, PA_IO_EVENT_INPUT, io_event_cb, u); - + do { if ((r = handle_event(u)) < 0) goto fail; @@ -445,7 +445,7 @@ int pa__init(pa_core *c, pa_module*m) { /* Read until the client signalled us that it is ready with * initialization */ } while (r != 1); - + return 0; fail: -- cgit From a67c21f093202f142438689d3f7cfbdf4ea82eea Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 28 Oct 2007 19:13:50 +0000 Subject: merge 'lennart' branch back into trunk. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1971 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/gconf/module-gconf.c | 99 ++++++++++++++++++++++++++-------------- 1 file changed, 65 insertions(+), 34 deletions(-) (limited to 'src/modules/gconf/module-gconf.c') diff --git a/src/modules/gconf/module-gconf.c b/src/modules/gconf/module-gconf.c index cbe17d20..1c8866de 100644 --- a/src/modules/gconf/module-gconf.c +++ b/src/modules/gconf/module-gconf.c @@ -25,7 +25,6 @@ #include #endif -#include #include #include #include @@ -34,6 +33,7 @@ #include #include #include +#include #ifdef HAVE_SYS_PRCTL_H #include @@ -95,7 +95,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"); @@ -111,21 +111,21 @@ static int fill_buf(struct userdata *u) { 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; @@ -143,9 +143,9 @@ 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); + pa_assert(u); + pa_assert(m); + pa_assert(i < m->n_items); if (m->items[i].index == PA_INVALID_INDEX) return; @@ -161,8 +161,8 @@ static void unload_one_module(struct userdata *u, struct module_info*m, unsigned static void unload_all_modules(struct userdata *u, struct module_info*m) { unsigned i; - assert(u); - assert(m); + pa_assert(u); + pa_assert(m); for (i = 0; i < m->n_items; i++) unload_one_module(u, m, i); @@ -180,10 +180,10 @@ static void load_module( pa_module *mod; - assert(u); - assert(m); - assert(name); - assert(args); + pa_assert(u); + pa_assert(m); + pa_assert(name); + pa_assert(args); if (!is_new) { if (m->items[i].index != PA_INVALID_INDEX && @@ -212,8 +212,8 @@ static void module_info_free(void *p, void *userdata) { struct module_info *m = p; struct userdata *u = userdata; - assert(m); - assert(u); + pa_assert(m); + pa_assert(u); unload_all_modules(u, m); pa_xfree(m->name); @@ -356,8 +356,10 @@ static int start_client(const char *n, pid_t *pid) { return pipe_fds[0]; } else { +#ifdef __linux__ + DIR* d; +#endif int max_fd, i; - /* child */ close(pipe_fds[0]); @@ -372,18 +374,48 @@ static int start_client(const char *n, pid_t *pid) { close(2); open("/dev/null", O_WRONLY); - max_fd = 1024; +#ifdef __linux__ + + if ((d = opendir("/proc/self/fd/"))) { + + struct dirent *de; + + while ((de = readdir(d))) { + char *e = NULL; + int fd; + + if (de->d_name[0] == '.') + continue; + + errno = 0; + fd = strtol(de->d_name, &e, 10); + pa_assert(errno == 0 && e && *e == 0); + + if (fd >= 3 && dirfd(d) != fd) + close(fd); + } + + closedir(d); + } else { + +#endif + + max_fd = 1024; #ifdef HAVE_SYS_RESOURCE_H - { - struct rlimit r; - if (getrlimit(RLIMIT_NOFILE, &r) == 0) - max_fd = r.rlim_max; - } + { + struct rlimit r; + if (getrlimit(RLIMIT_NOFILE, &r) == 0) + max_fd = r.rlim_max; + } #endif - for (i = 3; i < max_fd; i++) - close(i); + for (i = 3; i < max_fd; i++) + close(i); +# +#ifdef __linux__ + } +#endif #ifdef PR_SET_PDEATHSIG /* On Linux we can use PR_SET_PDEATHSIG to have the helper @@ -413,12 +445,12 @@ fail: 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); @@ -431,8 +463,8 @@ int pa__init(pa_core *c, pa_module*m) { if ((u->fd = start_client(PA_GCONF_HELPER, &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,21 +481,20 @@ 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); + m->core->mainloop->io_free(u->io_event); if (u->fd >= 0) close(u->fd); -- cgit From 2d265a91ccd84e896f2bca9764147630d0d7d003 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 30 Oct 2007 00:17:21 +0000 Subject: deal properly with signals interrupting us when we wait for data from gconf helper git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1992 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/gconf/module-gconf.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/modules/gconf/module-gconf.c') diff --git a/src/modules/gconf/module-gconf.c b/src/modules/gconf/module-gconf.c index 1c8866de..c2ea7b27 100644 --- a/src/modules/gconf/module-gconf.c +++ b/src/modules/gconf/module-gconf.c @@ -225,8 +225,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 '!': @@ -509,4 +512,3 @@ void pa__done(pa_module*m) { pa_xfree(u); } - -- cgit From 641d1fa96485f7a258ad958c4031e655767808a8 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 1 Nov 2007 02:55:06 +0000 Subject: drop rt scheduling before we start our helper process git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2013 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/gconf/module-gconf.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/modules/gconf/module-gconf.c') diff --git a/src/modules/gconf/module-gconf.c b/src/modules/gconf/module-gconf.c index c2ea7b27..799bdfbd 100644 --- a/src/modules/gconf/module-gconf.c +++ b/src/modules/gconf/module-gconf.c @@ -365,6 +365,8 @@ static int start_client(const char *n, pid_t *pid) { int max_fd, i; /* child */ + pa_reset_priority(); + close(pipe_fds[0]); dup2(pipe_fds[1], 1); -- cgit From e313fe1b3d0d9f9945c41c151d72edbe9cf1ec54 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 9 Nov 2007 18:25:40 +0000 Subject: tag modules that may only be loaded once at most especially, and enforce that in the module loader git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2043 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/gconf/module-gconf.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/modules/gconf/module-gconf.c') diff --git a/src/modules/gconf/module-gconf.c b/src/modules/gconf/module-gconf.c index 799bdfbd..fa9ab1cc 100644 --- a/src/modules/gconf/module-gconf.c +++ b/src/modules/gconf/module-gconf.c @@ -53,10 +53,10 @@ #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 -- cgit From e8092bede9c2c9daac6c6035ca7a130b2c9a7e5b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 11 Nov 2007 23:01:44 +0000 Subject: Port module-gconf to make use of the new API pa_start_child_for_read() git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2047 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/gconf/module-gconf.c | 137 +++------------------------------------ 1 file changed, 9 insertions(+), 128 deletions(-) (limited to 'src/modules/gconf/module-gconf.c') diff --git a/src/modules/gconf/module-gconf.c b/src/modules/gconf/module-gconf.c index fa9ab1cc..836157d0 100644 --- a/src/modules/gconf/module-gconf.c +++ b/src/modules/gconf/module-gconf.c @@ -33,23 +33,16 @@ #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" @@ -337,119 +330,6 @@ static void io_event_cb( } } -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 { -#ifdef __linux__ - DIR* d; -#endif - int max_fd, i; - /* child */ - - pa_reset_priority(); - - 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); - -#ifdef __linux__ - - if ((d = opendir("/proc/self/fd/"))) { - - struct dirent *de; - - while ((de = readdir(d))) { - char *e = NULL; - int fd; - - if (de->d_name[0] == '.') - continue; - - errno = 0; - fd = strtol(de->d_name, &e, 10); - pa_assert(errno == 0 && e && *e == 0); - - if (fd >= 3 && dirfd(d) != fd) - close(fd); - } - - closedir(d); - } else { - -#endif - - 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 __linux__ - } -#endif - -#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); - } - -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_module*m) { struct userdata *u; int r; @@ -465,7 +345,7 @@ int pa__init(pa_module*m) { 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(PA_GCONF_HELPER, NULL, &u->pid)) < 0) goto fail; u->io_event = m->core->mainloop->io_new( @@ -498,16 +378,17 @@ void pa__done(pa_module*m) { if (!(u = m->userdata)) return; + if (u->pid != (pid_t) -1) { + kill(u->pid, SIGTERM); + waitpid(u->pid, NULL, 0); + } + if (u->io_event) m->core->mainloop->io_free(u->io_event); if (u->fd >= 0) - close(u->fd); + pa_close(u->fd); - if (u->pid != (pid_t) -1) { - kill(u->pid, SIGTERM); - waitpid(u->pid, NULL, 0); - } if (u->module_infos) pa_hashmap_free(u->module_infos, module_info_free, u); -- cgit