mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-11-02 09:01:46 -05:00
correct autospawning
git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@202 fefdeb5f-60dc-0310-8127-8f9354f1896f
This commit is contained in:
parent
935826f4f3
commit
8c110d904d
13 changed files with 187 additions and 136 deletions
|
|
@ -25,7 +25,8 @@ modlibdir=$(libdir)/polypaudio-@PA_MAJORMINOR@
|
||||||
AM_CFLAGS=-D_GNU_SOURCE -I$(top_srcdir) $(PTHREAD_CFLAGS)
|
AM_CFLAGS=-D_GNU_SOURCE -I$(top_srcdir) $(PTHREAD_CFLAGS)
|
||||||
AM_CFLAGS+=-DDLSEARCHPATH=\"$(modlibdir)\"
|
AM_CFLAGS+=-DDLSEARCHPATH=\"$(modlibdir)\"
|
||||||
AM_CFLAGS+=-DDEFAULT_SCRIPT_FILE=\"$(polypconfdir)/default.pa\"
|
AM_CFLAGS+=-DDEFAULT_SCRIPT_FILE=\"$(polypconfdir)/default.pa\"
|
||||||
AM_CFLAGS+=-DDEFAULT_CONFIG_FILE=\"$(polypconfdir)/config\"
|
AM_CFLAGS+=-DDEFAULT_CONFIG_FILE=\"$(polypconfdir)/default.conf\"
|
||||||
|
AM_CFLAGS+=-DAUTOSPAWN_CONFIG_FILE=\"$(polypconfdir)/autospawn.conf\"
|
||||||
AM_CFLAGS+=-DPOLYPAUDIO_BINARY=\"$(bindir)/polypaudio\"
|
AM_CFLAGS+=-DPOLYPAUDIO_BINARY=\"$(bindir)/polypaudio\"
|
||||||
|
|
||||||
AM_LDADD=$(PTHREAD_LIBS) -lm
|
AM_LDADD=$(PTHREAD_LIBS) -lm
|
||||||
|
|
|
||||||
30
polyp/conf.c
30
polyp/conf.c
|
|
@ -53,17 +53,23 @@ static const struct pa_conf default_conf = {
|
||||||
|
|
||||||
#define ENV_SCRIPT_FILE "POLYP_SCRIPT"
|
#define ENV_SCRIPT_FILE "POLYP_SCRIPT"
|
||||||
#define ENV_CONFIG_FILE "POLYP_CONFIG"
|
#define ENV_CONFIG_FILE "POLYP_CONFIG"
|
||||||
|
#define ENV_AUTOSPAWNED "POLYP_AUTOSPAWNED"
|
||||||
|
|
||||||
#ifndef DEFAULT_SCRIPT_FILE
|
#ifndef DEFAULT_SCRIPT_FILE
|
||||||
#define DEFAULT_SCRIPT_FILE "/etc/polypaudio/default.pa"
|
#define DEFAULT_SCRIPT_FILE "/etc/polypaudio/default.pa"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef DEFAULT_CONFIG_FILE
|
#ifndef DEFAULT_CONFIG_FILE
|
||||||
#define DEFAULT_CONFIG_FILE "/etc/polypaudio/config"
|
#define DEFAULT_CONFIG_FILE "/etc/polypaudio/default.conf"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef AUTOSPAWN_CONFIG_FILE
|
||||||
|
#define AUTOSPAWN_CONFIG_FILE "/etc/polypaudio/autospawn.conf"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define DEFAULT_SCRIPT_FILE_LOCAL ".polypaudio.pa"
|
#define DEFAULT_SCRIPT_FILE_LOCAL ".polypaudio.pa"
|
||||||
#define DEFAULT_CONFIG_FILE_LOCAL ".polypaudio.conf"
|
#define DEFAULT_CONFIG_FILE_LOCAL ".polypaudio.conf"
|
||||||
|
#define AUTOSPAWN_CONFIG_FILE_LOCAL ".polypaudio-autospawn.conf"
|
||||||
|
|
||||||
char* default_file(const char *envvar, const char *global, const char *local) {
|
char* default_file(const char *envvar, const char *global, const char *local) {
|
||||||
char *p, *h;
|
char *p, *h;
|
||||||
|
|
@ -85,10 +91,26 @@ char* default_file(const char *envvar, const char *global, const char *local) {
|
||||||
return pa_xstrdup(global);
|
return pa_xstrdup(global);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *default_config_file(void) {
|
||||||
|
char *b;
|
||||||
|
int autospawned = 0;
|
||||||
|
|
||||||
|
if ((b = getenv(ENV_AUTOSPAWNED)))
|
||||||
|
autospawned = pa_parse_boolean(b) > 0;
|
||||||
|
|
||||||
|
return default_file(ENV_CONFIG_FILE,
|
||||||
|
autospawned ? AUTOSPAWN_CONFIG_FILE : DEFAULT_CONFIG_FILE,
|
||||||
|
autospawned ? AUTOSPAWN_CONFIG_FILE_LOCAL : DEFAULT_CONFIG_FILE_LOCAL);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
char *default_script_file(void) {
|
||||||
|
return default_file(ENV_SCRIPT_FILE, DEFAULT_SCRIPT_FILE, DEFAULT_SCRIPT_FILE_LOCAL);
|
||||||
|
}
|
||||||
|
|
||||||
struct pa_conf* pa_conf_new(void) {
|
struct pa_conf* pa_conf_new(void) {
|
||||||
struct pa_conf *c = pa_xmemdup(&default_conf, sizeof(default_conf));
|
struct pa_conf *c = pa_xmemdup(&default_conf, sizeof(default_conf));
|
||||||
c->default_script_file = default_file(ENV_SCRIPT_FILE, DEFAULT_SCRIPT_FILE, DEFAULT_SCRIPT_FILE_LOCAL);
|
c->default_script_file = default_script_file();
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -223,7 +245,7 @@ int pa_conf_load(struct pa_conf *c, const char *filename) {
|
||||||
assert(c);
|
assert(c);
|
||||||
|
|
||||||
if (!filename)
|
if (!filename)
|
||||||
filename = def = default_file(ENV_CONFIG_FILE, DEFAULT_CONFIG_FILE, DEFAULT_CONFIG_FILE_LOCAL);
|
filename = def = default_config_file();
|
||||||
|
|
||||||
if (!(f = fopen(filename, "r"))) {
|
if (!(f = fopen(filename, "r"))) {
|
||||||
if (errno != ENOENT)
|
if (errno != ENOENT)
|
||||||
|
|
@ -259,7 +281,7 @@ char *pa_conf_dump(struct pa_conf *c) {
|
||||||
struct pa_strbuf *s = pa_strbuf_new();
|
struct pa_strbuf *s = pa_strbuf_new();
|
||||||
char *d;
|
char *d;
|
||||||
|
|
||||||
d = default_file(ENV_CONFIG_FILE, DEFAULT_CONFIG_FILE, DEFAULT_CONFIG_FILE_LOCAL);
|
d = default_config_file();
|
||||||
pa_strbuf_printf(s, "### Default configuration file: %s ###\n", d);
|
pa_strbuf_printf(s, "### Default configuration file: %s ###\n", d);
|
||||||
|
|
||||||
pa_strbuf_printf(s, "verbose = %i\n", !!c->verbose);
|
pa_strbuf_printf(s, "verbose = %i\n", !!c->verbose);
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
#include "core.h"
|
#include "core.h"
|
||||||
#include "module.h"
|
#include "module.h"
|
||||||
|
|
@ -79,7 +80,7 @@ struct pa_core* pa_core_new(struct pa_mainloop_api *m) {
|
||||||
c->module_idle_time = 20;
|
c->module_idle_time = 20;
|
||||||
c->scache_idle_time = 20;
|
c->scache_idle_time = 20;
|
||||||
|
|
||||||
pa_check_for_sigpipe();
|
pa_check_signal_is_blocked(SIGPIPE);
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
14
polyp/main.c
14
polyp/main.c
|
|
@ -58,20 +58,8 @@ static void drop_root(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char* signal_name(int s) {
|
|
||||||
switch(s) {
|
|
||||||
case SIGINT: return "SIGINT";
|
|
||||||
case SIGTERM: return "SIGTERM";
|
|
||||||
case SIGUSR1: return "SIGUSR1";
|
|
||||||
case SIGUSR2: return "SIGUSR2";
|
|
||||||
case SIGXCPU: return "SIGXCPU";
|
|
||||||
case SIGPIPE: return "SIGPIPE";
|
|
||||||
default: return "UNKNOWN SIGNAL";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void signal_callback(struct pa_mainloop_api*m, struct pa_signal_event *e, int sig, void *userdata) {
|
static void signal_callback(struct pa_mainloop_api*m, struct pa_signal_event *e, int sig, void *userdata) {
|
||||||
pa_log(__FILE__": Got signal %s.\n", signal_name(sig));
|
pa_log(__FILE__": Got signal %s.\n", pa_strsignal(sig));
|
||||||
|
|
||||||
switch (sig) {
|
switch (sig) {
|
||||||
case SIGUSR1:
|
case SIGUSR1:
|
||||||
|
|
|
||||||
|
|
@ -360,7 +360,7 @@ int main(int argc, char *argv[]) {
|
||||||
pa_context_set_state_callback(context, context_state_callback, NULL);
|
pa_context_set_state_callback(context, context_state_callback, NULL);
|
||||||
|
|
||||||
/* Connect the context */
|
/* Connect the context */
|
||||||
pa_context_connect_spawn(context, NULL, NULL, NULL);
|
pa_context_connect(context, NULL, 1, NULL);
|
||||||
|
|
||||||
/* Run the main loop */
|
/* Run the main loop */
|
||||||
if (pa_mainloop_run(m, &ret) < 0) {
|
if (pa_mainloop_run(m, &ret) < 0) {
|
||||||
|
|
|
||||||
|
|
@ -292,7 +292,7 @@ int main(int argc, char *argv[]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
pa_context_set_state_callback(context, context_state_callback, NULL);
|
pa_context_set_state_callback(context, context_state_callback, NULL);
|
||||||
pa_context_connect(context, NULL);
|
pa_context_connect(context, NULL, 1, NULL);
|
||||||
|
|
||||||
if (pa_mainloop_run(m, &ret) < 0) {
|
if (pa_mainloop_run(m, &ret) < 0) {
|
||||||
fprintf(stderr, "pa_mainloop_run() failed.\n");
|
fprintf(stderr, "pa_mainloop_run() failed.\n");
|
||||||
|
|
|
||||||
|
|
@ -85,7 +85,7 @@ struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *
|
||||||
|
|
||||||
c->memblock_stat = pa_memblock_stat_new();
|
c->memblock_stat = pa_memblock_stat_new();
|
||||||
|
|
||||||
pa_check_for_sigpipe();
|
pa_check_signal_is_blocked(SIGPIPE);
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -365,15 +365,116 @@ static struct sockaddr *resolve_server(const char *server, size_t *len) {
|
||||||
return sa;
|
return sa;
|
||||||
}
|
}
|
||||||
|
|
||||||
int pa_context_connect(struct pa_context *c, const char *server) {
|
static int is_running(void) {
|
||||||
|
struct stat st;
|
||||||
|
|
||||||
|
if (DEFAULT_SERVER[0] != '/')
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (stat(DEFAULT_SERVER, &st) < 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int context_connect_spawn(struct pa_context *c, const struct pa_spawn_api *api) {
|
||||||
|
pid_t pid;
|
||||||
|
int status, r;
|
||||||
|
int fds[2] = { -1, -1} ;
|
||||||
|
struct pa_iochannel *io;
|
||||||
|
|
||||||
|
if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) {
|
||||||
|
pa_log(__FILE__": socketpair() failed: %s\n", strerror(errno));
|
||||||
|
pa_context_fail(c, PA_ERROR_INTERNAL);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (api && api->prefork)
|
||||||
|
api->prefork();
|
||||||
|
|
||||||
|
if ((pid = fork()) < 0) {
|
||||||
|
pa_log(__FILE__": fork() failed: %s\n", strerror(errno));
|
||||||
|
pa_context_fail(c, PA_ERROR_INTERNAL);
|
||||||
|
|
||||||
|
if (api && api->postfork)
|
||||||
|
api->postfork();
|
||||||
|
|
||||||
|
goto fail;
|
||||||
|
} else if (!pid) {
|
||||||
|
char t[128];
|
||||||
|
char *p;
|
||||||
|
/* Child */
|
||||||
|
|
||||||
|
close(fds[0]);
|
||||||
|
|
||||||
|
if (api && api->atfork)
|
||||||
|
api->atfork();
|
||||||
|
|
||||||
|
if (!(p = getenv(ENV_DEFAULT_BINARY)))
|
||||||
|
p = POLYPAUDIO_BINARY;
|
||||||
|
|
||||||
|
snprintf(t, sizeof(t), "%s=1", ENV_AUTOSPAWNED);
|
||||||
|
putenv(t);
|
||||||
|
|
||||||
|
snprintf(t, sizeof(t), "-Lmodule-native-protocol-fd fd=%i", fds[1]);
|
||||||
|
execl(p, p, t, NULL);
|
||||||
|
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Parent */
|
||||||
|
|
||||||
|
r = waitpid(pid, &status, 0);
|
||||||
|
|
||||||
|
if (api && api->postfork)
|
||||||
|
api->postfork();
|
||||||
|
|
||||||
|
if (r < 0) {
|
||||||
|
pa_log(__FILE__": waitpid() failed: %s\n", strerror(errno));
|
||||||
|
pa_context_fail(c, PA_ERROR_INTERNAL);
|
||||||
|
goto fail;
|
||||||
|
} else if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
|
||||||
|
pa_context_fail(c, PA_ERROR_CONNECTIONREFUSED);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
close(fds[1]);
|
||||||
|
|
||||||
|
io = pa_iochannel_new(c->mainloop, fds[0], fds[0]);
|
||||||
|
setup_context(c, io);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
if (fds[0] != -1)
|
||||||
|
close(fds[0]);
|
||||||
|
if (fds[1] != -1)
|
||||||
|
close(fds[1]);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int pa_context_connect(struct pa_context *c, const char *server, int spawn, const struct pa_spawn_api *api) {
|
||||||
int r = -1;
|
int r = -1;
|
||||||
assert(c && c->ref >= 1 && c->state == PA_CONTEXT_UNCONNECTED);
|
assert(c && c->ref >= 1 && c->state == PA_CONTEXT_UNCONNECTED);
|
||||||
|
|
||||||
pa_context_ref(c);
|
|
||||||
|
|
||||||
if (!server)
|
if (!server)
|
||||||
if (!(server = getenv(ENV_DEFAULT_SERVER)))
|
if (!(server = getenv(ENV_DEFAULT_SERVER))) {
|
||||||
|
if (spawn && !is_running()) {
|
||||||
|
char *b;
|
||||||
|
|
||||||
|
if ((b = getenv(ENV_DISABLE_AUTOSPAWN)))
|
||||||
|
if (pa_parse_boolean(b) > 1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return context_connect_spawn(c, api);
|
||||||
|
}
|
||||||
|
|
||||||
server = DEFAULT_SERVER;
|
server = DEFAULT_SERVER;
|
||||||
|
}
|
||||||
|
|
||||||
|
pa_context_ref(c);
|
||||||
|
|
||||||
assert(!c->client);
|
assert(!c->client);
|
||||||
|
|
||||||
|
|
@ -562,94 +663,6 @@ const char* pa_get_library_version(void) {
|
||||||
return PACKAGE_VERSION;
|
return PACKAGE_VERSION;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int is_running(void) {
|
|
||||||
struct stat st;
|
|
||||||
|
|
||||||
if (DEFAULT_SERVER[0] != '/')
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (stat(DEFAULT_SERVER, &st) < 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int pa_context_connect_spawn(struct pa_context *c, void (*atfork)(void), void (*prefork)(void), void (*postfork)(void)) {
|
|
||||||
pid_t pid;
|
|
||||||
int status, r;
|
|
||||||
int fds[2] = { -1, -1} ;
|
|
||||||
struct pa_iochannel *io;
|
|
||||||
|
|
||||||
if (getenv(ENV_DEFAULT_SERVER) || is_running())
|
|
||||||
return pa_context_connect(c, NULL);
|
|
||||||
|
|
||||||
if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) {
|
|
||||||
pa_log(__FILE__": socketpair() failed: %s\n", strerror(errno));
|
|
||||||
pa_context_fail(c, PA_ERROR_INTERNAL);
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (prefork)
|
|
||||||
prefork();
|
|
||||||
|
|
||||||
if ((pid = fork()) < 0) {
|
|
||||||
pa_log(__FILE__": fork() failed: %s\n", strerror(errno));
|
|
||||||
pa_context_fail(c, PA_ERROR_INTERNAL);
|
|
||||||
|
|
||||||
if (postfork)
|
|
||||||
postfork();
|
|
||||||
|
|
||||||
goto fail;
|
|
||||||
} else if (!pid) {
|
|
||||||
char t[64];
|
|
||||||
char *p;
|
|
||||||
/* Child */
|
|
||||||
|
|
||||||
close(fds[0]);
|
|
||||||
|
|
||||||
if (atfork)
|
|
||||||
atfork();
|
|
||||||
|
|
||||||
if (!(p = getenv(ENV_DEFAULT_BINARY)))
|
|
||||||
p = POLYPAUDIO_BINARY;
|
|
||||||
|
|
||||||
snprintf(t, sizeof(t), "-Lmodule-native-protocol-fd fd=%i", fds[1]);
|
|
||||||
execl(p, p, "-r", "-D", "-lsyslog", "-X 5", t, NULL);
|
|
||||||
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Parent */
|
|
||||||
|
|
||||||
r = waitpid(pid, &status, 0);
|
|
||||||
|
|
||||||
if (postfork)
|
|
||||||
postfork();
|
|
||||||
|
|
||||||
if (r < 0) {
|
|
||||||
pa_log(__FILE__": waitpid() failed: %s\n", strerror(errno));
|
|
||||||
pa_context_fail(c, PA_ERROR_INTERNAL);
|
|
||||||
goto fail;
|
|
||||||
} else if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
|
|
||||||
pa_context_fail(c, PA_ERROR_CONNECTIONREFUSED);
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
close(fds[1]);
|
|
||||||
|
|
||||||
io = pa_iochannel_new(c->mainloop, fds[0], fds[0]);
|
|
||||||
setup_context(c, io);
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
fail:
|
|
||||||
if (fds[0] != -1)
|
|
||||||
close(fds[0]);
|
|
||||||
if (fds[1] != -1)
|
|
||||||
close(fds[1]);
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct pa_operation* pa_context_set_default_sink(struct pa_context *c, const char *name, void(*cb)(struct pa_context*c, int success, void *userdata), void *userdata) {
|
struct pa_operation* pa_context_set_default_sink(struct pa_context *c, const char *name, void(*cb)(struct pa_context*c, int success, void *userdata), void *userdata) {
|
||||||
struct pa_tagstruct *t;
|
struct pa_tagstruct *t;
|
||||||
struct pa_operation *o;
|
struct pa_operation *o;
|
||||||
|
|
|
||||||
|
|
@ -76,22 +76,11 @@ enum pa_context_state pa_context_get_state(struct pa_context *c);
|
||||||
/** Connect the context to the specified server. If server is NULL,
|
/** Connect the context to the specified server. If server is NULL,
|
||||||
connect to the default server. This routine may but will not always
|
connect to the default server. This routine may but will not always
|
||||||
return synchronously on error. Use pa_context_set_state_callback() to
|
return synchronously on error. Use pa_context_set_state_callback() to
|
||||||
be notified when the connection is established */
|
be notified when the connection is established. If spawn is non-zero
|
||||||
int pa_context_connect(struct pa_context *c, const char *server);
|
and no specific server is specified or accessible a new daemon is
|
||||||
|
spawned. If api is non-NULL, the functions specified in the structure
|
||||||
/** Connect the context to a server. If the default server is local
|
are used when forking a new child process. */
|
||||||
* but not accessible, spawn a new daemon. If atfork is not NULL it is
|
int pa_context_connect(struct pa_context *c, const char *server, int spawn, const struct pa_spawn_api *api);
|
||||||
* run after the fork() in the child process. It may be used to close
|
|
||||||
* file descriptors or to do any other cleanups. (It is not safe to
|
|
||||||
* close all file descriptors unconditionally, since a UNIX socket is
|
|
||||||
* passed to the new process.) if prefork is not NULL it is run just
|
|
||||||
* before forking in the parent process. Use this to block SIGCHLD
|
|
||||||
* handling if required. If postfork is not NULL it is run just after
|
|
||||||
* forking in the parent process. Use this to unblock SIGCHLD if
|
|
||||||
* required. The function will waitpid() on the daemon's PID, but
|
|
||||||
* will not block or ignore SIGCHLD signals, since this cannot be done
|
|
||||||
* in a thread compatible way. \since 0.4 */
|
|
||||||
int pa_context_connect_spawn(struct pa_context *c, void (*atfork)(void), void (*prefork)(void), void (*postfork)(void));
|
|
||||||
|
|
||||||
/** Terminate the context connection immediately */
|
/** Terminate the context connection immediately */
|
||||||
void pa_context_disconnect(struct pa_context *c);
|
void pa_context_disconnect(struct pa_context *c);
|
||||||
|
|
|
||||||
|
|
@ -156,6 +156,25 @@ struct pa_latency_info {
|
||||||
struct timeval timestamp; /**< The time when this latency info was current */
|
struct timeval timestamp; /**< The time when this latency info was current */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** A structure for the spawn api. This may be used to integrate auto
|
||||||
|
* spawned daemons into your application. For more information see
|
||||||
|
* pa_context_connect(). When spawning a new child process the
|
||||||
|
* waitpid() is used on the child's PID. The spawn routine will not
|
||||||
|
* block or ignore SIGCHLD signals, since this cannot be done in a
|
||||||
|
* thread compatible way. You might have to do this in
|
||||||
|
* prefork/postfork. \since 0.4 */
|
||||||
|
struct pa_spawn_api {
|
||||||
|
void (*prefork)(void); /**< Is called just before the fork in the parent process. May be NULL. */
|
||||||
|
void (*postfork)(void); /**< Is called immediately after the fork in the parent process. May be NULL.*/
|
||||||
|
void (*atfork)(void); /**< Is called immediately after the
|
||||||
|
* fork in the child process. May be
|
||||||
|
* NULL. It is not safe to close all
|
||||||
|
* file descriptors in this function
|
||||||
|
* unconditionally, since a UNIX socket
|
||||||
|
* (created using socketpair()) is
|
||||||
|
* passed to the new process. */
|
||||||
|
};
|
||||||
|
|
||||||
PA_C_DECL_END
|
PA_C_DECL_END
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,8 @@
|
||||||
#define ENV_DEFAULT_SOURCE "POLYP_SOURCE"
|
#define ENV_DEFAULT_SOURCE "POLYP_SOURCE"
|
||||||
#define ENV_DEFAULT_SERVER "POLYP_SERVER"
|
#define ENV_DEFAULT_SERVER "POLYP_SERVER"
|
||||||
#define ENV_DEFAULT_BINARY "POLYP_BINARY"
|
#define ENV_DEFAULT_BINARY "POLYP_BINARY"
|
||||||
|
#define ENV_DISABLE_AUTOSPAWN "POLYP_NOAUTOSPAWN"
|
||||||
|
#define ENV_AUTOSPAWNED "POLYP_AUTOSPAWNED"
|
||||||
|
|
||||||
struct pa_context {
|
struct pa_context {
|
||||||
int ref;
|
int ref;
|
||||||
|
|
|
||||||
|
|
@ -130,7 +130,7 @@ struct pa_simple* pa_simple_new(
|
||||||
if (!(p->context = pa_context_new(pa_mainloop_get_api(p->mainloop), name)))
|
if (!(p->context = pa_context_new(pa_mainloop_get_api(p->mainloop), name)))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
pa_context_connect(p->context, server);
|
pa_context_connect(p->context, server, 1, NULL);
|
||||||
|
|
||||||
/* Wait until the context is ready */
|
/* Wait until the context is ready */
|
||||||
while (pa_context_get_state(p->context) != PA_CONTEXT_READY) {
|
while (pa_context_get_state(p->context) != PA_CONTEXT_READY) {
|
||||||
|
|
|
||||||
22
polyp/util.c
22
polyp/util.c
|
|
@ -115,7 +115,7 @@ ssize_t pa_loop_write(int fd, const void*data, size_t size) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pa_check_for_sigpipe(void) {
|
void pa_check_signal_is_blocked(int sig) {
|
||||||
struct sigaction sa;
|
struct sigaction sa;
|
||||||
sigset_t set;
|
sigset_t set;
|
||||||
|
|
||||||
|
|
@ -130,10 +130,10 @@ void pa_check_for_sigpipe(void) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (sigismember(&set, SIGPIPE))
|
if (sigismember(&set, sig))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (sigaction(SIGPIPE, NULL, &sa) < 0) {
|
if (sigaction(sig, NULL, &sa) < 0) {
|
||||||
pa_log(__FILE__": sigaction() failed: %s\n", strerror(errno));
|
pa_log(__FILE__": sigaction() failed: %s\n", strerror(errno));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -141,7 +141,7 @@ void pa_check_for_sigpipe(void) {
|
||||||
if (sa.sa_handler != SIG_DFL)
|
if (sa.sa_handler != SIG_DFL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
pa_log(__FILE__": WARNING: SIGPIPE is not trapped. This might cause malfunction!\n");
|
pa_log(__FILE__": WARNING: %s is not trapped. This might cause malfunction!\n", pa_strsignal(sig));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The following is based on an example from the GNU libc documentation */
|
/* The following is based on an example from the GNU libc documentation */
|
||||||
|
|
@ -389,3 +389,17 @@ char *pa_split(const char *c, const char *delimiter, const char**state) {
|
||||||
|
|
||||||
return pa_xstrndup(current, l);
|
return pa_xstrndup(current, l);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *pa_strsignal(int sig) {
|
||||||
|
switch(sig) {
|
||||||
|
case SIGINT: return "SIGINT";
|
||||||
|
case SIGTERM: return "SIGTERM";
|
||||||
|
case SIGUSR1: return "SIGUSR1";
|
||||||
|
case SIGUSR2: return "SIGUSR2";
|
||||||
|
case SIGXCPU: return "SIGXCPU";
|
||||||
|
case SIGPIPE: return "SIGPIPE";
|
||||||
|
case SIGCHLD: return "SIGCHLD";
|
||||||
|
default: return "UNKNOWN SIGNAL";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ int pa_make_secure_dir(const char* dir);
|
||||||
ssize_t pa_loop_read(int fd, void*data, size_t size);
|
ssize_t pa_loop_read(int fd, void*data, size_t size);
|
||||||
ssize_t pa_loop_write(int fd, const void*data, size_t size);
|
ssize_t pa_loop_write(int fd, const void*data, size_t size);
|
||||||
|
|
||||||
void pa_check_for_sigpipe(void);
|
void pa_check_signal_is_blocked(int sig);
|
||||||
|
|
||||||
char *pa_sprintf_malloc(const char *format, ...) PA_GCC_PRINTF_ATTR(1,2);
|
char *pa_sprintf_malloc(const char *format, ...) PA_GCC_PRINTF_ATTR(1,2);
|
||||||
char *pa_vsprintf_malloc(const char *format, va_list ap);
|
char *pa_vsprintf_malloc(const char *format, va_list ap);
|
||||||
|
|
@ -61,4 +61,6 @@ int pa_parse_boolean(const char *s);
|
||||||
|
|
||||||
char *pa_split(const char *c, const char*delimiters, const char **state);
|
char *pa_split(const char *c, const char*delimiters, const char **state);
|
||||||
|
|
||||||
|
const char *pa_strsignal(int sig);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue