From: Andre Noll Date: Sun, 3 May 2009 17:09:16 +0000 (+0200) Subject: Merge branch 'master' into next X-Git-Tag: v0.3.5~61^2 X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=commitdiff_plain;h=343f3c63fc3a7f9ca4ba4163c9e4cf06cde8d0c3;hp=9b5d9adba31e6d42b9dde81fcd3b6f8a0b16bcfc Merge branch 'master' into next --- diff --git a/afs.c b/afs.c index 6233e2d1..72e2490e 100644 --- a/afs.c +++ b/afs.c @@ -805,10 +805,7 @@ static void register_signal_task(void) { struct signal_task *st = &signal_task_struct; - if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) { - PARA_EMERG_LOG("failed to ignore SIGPIPE\n"); - exit(EXIT_FAILURE); - } + para_sigaction(SIGPIPE, SIG_IGN); st->fd = para_signal_init(); PARA_INFO_LOG("signal pipe: fd %d\n", st->fd); para_install_sighandler(SIGINT); diff --git a/alsa_write.c b/alsa_write.c index 0bb3de38..456c5178 100644 --- a/alsa_write.c +++ b/alsa_write.c @@ -167,7 +167,7 @@ static int alsa_write_post_select(__a_unused struct sched *s, struct private_alsa_write_data *pad = wn->private_data; struct writer_node_group *wng = wn->wng; size_t frames, bytes = *wng->loaded - wn->written; - unsigned char *data = (unsigned char*)wng->buf + wn->written; + unsigned char *data = (unsigned char*)*wng->bufp + wn->written; struct timeval tv; snd_pcm_sframes_t ret; diff --git a/audiod.c b/audiod.c index 3a2607de..77819654 100644 --- a/audiod.c +++ b/audiod.c @@ -286,7 +286,7 @@ static void setup_signal_handling(void) para_install_sighandler(SIGINT); para_install_sighandler(SIGTERM); para_install_sighandler(SIGHUP); - signal(SIGPIPE, SIG_IGN); + para_sigaction(SIGPIPE, SIG_IGN); } static void clear_slot(int slot_num) @@ -382,7 +382,7 @@ static void open_filters(int slot_num) PARA_INFO_LOG("opening %s filters\n", audio_formats[s->format]); s->fc = para_calloc(sizeof(struct filter_chain)); s->fc->filter_nodes = para_malloc(nf * sizeof(struct filter_node)); - s->fc->inbuf = s->receiver_node->buf; + s->fc->inbufp = &s->receiver_node->buf; s->fc->in_loaded = &s->receiver_node->loaded; s->fc->input_error = &s->receiver_node->task.error; s->fc->task.pre_select = filter_pre_select; @@ -402,7 +402,7 @@ static void open_filters(int slot_num) f->open(fn); PARA_NOTICE_LOG("%s filter %d/%d (%s) started in slot %d\n", audio_formats[s->format], i, nf, f->name, slot_num); - s->fc->outbuf = fn->buf; + s->fc->outbufp = &fn->buf; s->fc->out_loaded = &fn->loaded; } register_task(&s->fc->task); @@ -420,7 +420,7 @@ static void open_writers(int slot_num) else s->wng = wng_new(a->num_writers); if (s->fc) { - s->wng->buf = s->fc->outbuf; + s->wng->bufp = s->fc->outbufp; s->wng->loaded = s->fc->out_loaded; s->wng->input_error = &s->fc->task.error; s->wng->channels = &s->fc->channels; @@ -428,7 +428,7 @@ static void open_writers(int slot_num) s->fc->output_error = &s->wng->task.error; PARA_INFO_LOG("samplerate: %d\n", *s->wng->samplerate); } else { - s->wng->buf = s->receiver_node->buf; + s->wng->bufp = &s->receiver_node->buf; s->wng->loaded = &s->receiver_node->loaded; s->wng->input_error = &s->receiver_node->task.error; } diff --git a/client.c b/client.c index 2123421e..003c1e60 100644 --- a/client.c +++ b/client.c @@ -40,7 +40,7 @@ static void supervisor_post_select(__a_unused struct sched *s, struct task *t) } if (ct->status == CL_RECEIVING) { stdout_set_defaults(&sot); - sot.buf = ct->buf; + sot.bufp = &ct->buf; sot.loaded = &ct->loaded; sot.input_error = &ct->task.error; register_task(&sot.task); diff --git a/client.h b/client.h index a7a3289b..c6d5c75d 100644 --- a/client.h +++ b/client.h @@ -58,7 +58,7 @@ struct client_task { /** the client task structure */ struct task task; /** the buffer used for handshake and receiving */ - char buf[CLIENT_BUFSIZE]; + char *buf; /** number of bytes loaded in \p buf */ size_t loaded; /** non-zero if the pre_select hook added \p fd to the read fd set */ diff --git a/client_common.c b/client_common.c index c1e23f7a..5bce7fb4 100644 --- a/client_common.c +++ b/client_common.c @@ -64,6 +64,7 @@ void client_close(struct client_task *ct) disable_crypt(ct->fd); close(ct->fd); } + free(ct->buf); free(ct->user); free(ct->config_file); free(ct->key_file); @@ -327,6 +328,7 @@ int client_open(int argc, char *argv[], struct client_task **ct_ptr, int ret; struct client_task *ct = para_calloc(sizeof(struct client_task)); + ct->buf = para_malloc(CLIENT_BUFSIZE); *ct_ptr = ct; ct->fd = -1; ret = -E_CLIENT_SYNTAX; diff --git a/command.c b/command.c index 698e2755..1ca54da9 100644 --- a/command.c +++ b/command.c @@ -30,6 +30,8 @@ #include "user_list.h" #include "server_command_list.h" #include "afs_command_list.h" +#include "sched.h" +#include "signal.h" /** Commands including options must be shorter than this. */ #define MAX_COMMAND_LEN 32768 @@ -42,15 +44,8 @@ extern int mmd_mutex; extern struct misc_meta_data *mmd; extern struct sender senders[]; -static void dummy(int s) +static void dummy(__a_unused int s) { - /* - * At least on Solaris, SIGUSR1 is one-shot, i.e. the signal action is - * restored to the default state once the signal handler has been - * called. - */ - if (s == SIGUSR1) - signal(SIGUSR1, dummy); } static void mmd_dup(struct misc_meta_data *new_mmd) @@ -113,7 +108,7 @@ static char *get_status(struct misc_meta_data *nmmd) char *status, *flags; /* vss status info */ char *ut = uptime_str(); long offset = (nmmd->offset + 500) / 1000; - struct timeval now; + struct timeval current_time; struct tm mtime_tm; /* report real status */ @@ -123,7 +118,7 @@ static char *get_status(struct misc_meta_data *nmmd) localtime_r(&nmmd->mtime, &mtime_tm); strftime(mtime, 29, "%b %d %Y", &mtime_tm); } - gettimeofday(&now, NULL); + gettimeofday(¤t_time, NULL); ret = make_message( "%s: %zu\n" /* file size */ "%s: %s\n" /* mtime */ @@ -146,8 +141,8 @@ static char *get_status(struct misc_meta_data *nmmd) (long unsigned)nmmd->stream_start.tv_sec, (long unsigned)nmmd->stream_start.tv_usec, status_item_list[SI_CURRENT_TIME], - (long unsigned)now.tv_sec, - (long unsigned)now.tv_usec, + (long unsigned)current_time.tv_sec, + (long unsigned)current_time.tv_usec, nmmd->afd.verbose_ls_output @@ -318,7 +313,7 @@ int com_stat(int fd, int argc, char * const * argv) struct misc_meta_data tmp, *nmmd = &tmp; char *s; - signal(SIGUSR1, dummy); + para_sigaction(SIGUSR1, dummy); if (argc > 1) num = atoi(argv[1]); @@ -655,6 +650,14 @@ out: } +static void reset_signals(void) +{ + para_sigaction(SIGCHLD, SIG_IGN); + para_sigaction(SIGINT, SIG_DFL); + para_sigaction(SIGTERM, SIG_DFL); + para_sigaction(SIGHUP, SIG_DFL); +} + /** * Perform user authentication and execute a command. * @@ -694,11 +697,7 @@ __noreturn void handle_connect(int fd, const char *peername) char *p, *command = NULL; size_t numbytes; - signal(SIGCHLD, SIG_IGN); - signal(SIGINT, SIG_DFL); - signal(SIGTERM, SIG_DFL); - signal(SIGHUP, SIG_DFL); - + reset_signals(); /* we need a blocking fd here as recv() might return EAGAIN otherwise. */ ret = mark_fd_blocking(fd); if (ret < 0) diff --git a/error.h b/error.h index 60415223..555ca15f 100644 --- a/error.h +++ b/error.h @@ -29,6 +29,8 @@ DEFINE_ERRLIST_OBJECT_ENUM; #define HTTP_SEND_ERRORS #define GGO_ERRORS #define COLOR_ERRORS +#define SIGNAL_ERRORS + extern const char **para_errlist[]; @@ -299,10 +301,6 @@ extern const char **para_errlist[]; PARA_ERROR(FILTER_SYNTAX, "syntax error"), \ -#define SIGNAL_ERRORS \ - PARA_ERROR(SIGNAL_SIG_ERR, "signal() returned SIG_ERR"), \ - - #define STRING_ERRORS \ PARA_ERROR(ATOI_OVERFLOW, "value too large"), \ PARA_ERROR(STRTOLL, "unknown strtoll error"), \ diff --git a/fecdec_filter.c b/fecdec_filter.c index 5f37f1a8..1f57dd12 100644 --- a/fecdec_filter.c +++ b/fecdec_filter.c @@ -27,8 +27,10 @@ */ #define NUM_FEC_GROUPS 3 -/** Size of the output buffer of the fecdec filter. */ -#define FECDEC_OUTBUF_SIZE (1024 * 1024) /* FIXME: This has to depend on the fec params */ +/** Default size of the output buffer of the fecdec filter. */ +#define FECDEC_DEFAULT_OUTBUF_SIZE (3 * 1024) +/** Maximal size of the output buffer of the fecdec filter. */ +#define FECDEC_MAX_OUTBUF_SIZE (1024 * 1024) /** Data read from the header of a slice. */ struct fec_header { @@ -256,7 +258,7 @@ static enum fec_group_usability group_is_usable(struct fecdec_group *fg, static int decode_group(struct fecdec_group *fg, struct filter_node *fn) { int i, ret, sb = fg->h.slice_bytes; - size_t written = 0; + size_t written = 0, need; struct private_fecdec_data *pfd = fn->private_data; enum fec_group_usability u = group_is_usable(fg, pfd); @@ -279,12 +281,18 @@ static int decode_group(struct fecdec_group *fg, struct filter_node *fn) PARA_DEBUG_LOG("writing group %d (%d/%d decoded data bytes)\n", fg->h.group_num, fg->h.group_bytes, fg->h.data_slices_per_group * sb); + need = fn->loaded + (fg->h.data_slices_per_group - i)* sb; + if (need > fn->bufsize) { + fn->bufsize = PARA_MAX(fn->bufsize * 2, need); + if (fn->bufsize > FECDEC_MAX_OUTBUF_SIZE) + return -E_FECDEC_OVERRUN; + PARA_INFO_LOG("increasing fec buf to %zu\n", fn->bufsize); + fn->buf = para_realloc(fn->buf, fn->bufsize); + } for (; i < fg->h.data_slices_per_group; i++) { size_t n = sb; if (n + written > fg->h.group_bytes) n = fg->h.group_bytes - written; - if (fn->loaded + n > fn->bufsize) - return -E_FECDEC_OVERRUN; memcpy(fn->buf + fn->loaded, fg->data[i], n); fn->loaded += n; written += n; @@ -391,7 +399,7 @@ static void fecdec_close(struct filter_node *fn) static void fecdec_open(struct filter_node *fn) { - fn->bufsize = FECDEC_OUTBUF_SIZE; + fn->bufsize = FECDEC_DEFAULT_OUTBUF_SIZE; fn->buf = para_malloc(fn->bufsize); fn->private_data = para_calloc(sizeof(struct private_fecdec_data)); fn->loaded = 0; diff --git a/file_write.c b/file_write.c index 0950e303..92777d7d 100644 --- a/file_write.c +++ b/file_write.c @@ -79,7 +79,7 @@ static int file_write_post_select(struct sched *s, struct writer_node *wn) if (!FD_ISSET(pfwd->fd, &s->wfds)) return 1; // PARA_INFO_LOG("writing %zd\n", *wng->loaded); - ret = write(pfwd->fd, wng->buf + wn->written, + ret = write(pfwd->fd, *wng->bufp + wn->written, *wng->loaded - wn->written); if (ret < 0) return -E_FW_WRITE; diff --git a/filter.c b/filter.c index 9311a20a..b8a7c5c1 100644 --- a/filter.c +++ b/filter.c @@ -56,7 +56,7 @@ static void open_filters(void) struct filter *f = filters + fn->filter_num; f->open(fn); PARA_INFO_LOG("opened %s filter\n", f->name); - fc->outbuf = fn->buf; + fc->outbufp = &fn->buf; fc->out_loaded = &fn->loaded; } } @@ -70,7 +70,7 @@ static int init_filter_chain(void) return -E_NO_FILTERS; fc->num_filters = conf.filter_given; fc->filter_nodes = para_malloc(fc->num_filters * sizeof(struct filter_node)); - fc->inbuf = sit->buf; + fc->inbufp = &sit->buf; fc->in_loaded = &sit->loaded; fc->input_error = &sit->task.error; fc->task.error = 0; @@ -170,7 +170,7 @@ int main(int argc, char *argv[]) sit->output_error = &fc->task.error; stdout_set_defaults(sot); - sot->buf = fc->outbuf; + sot->bufp = fc->outbufp; sot->loaded = fc->out_loaded; sot->input_error = &fc->task.error; diff --git a/filter.h b/filter.h index da472905..0bb51f5a 100644 --- a/filter.h +++ b/filter.h @@ -59,13 +59,13 @@ struct filter_chain { * buffer used to read from stdin for para_filter; the output buffer of the * current receiver for para_audiod). */ - char *inbuf; + char **inbufp; /** * The output buffer of the filter chain. * * Points to the output buffer of the last filter in the filter chain. */ - char *outbuf; + char **outbufp; /** Contains the number of bytes loaded in the input buffer. */ size_t *in_loaded; /** Contains the number of bytes loaded in the output buffer. */ diff --git a/filter_common.c b/filter_common.c index b601c688..ebda1ee7 100644 --- a/filter_common.c +++ b/filter_common.c @@ -118,7 +118,7 @@ void filter_pre_select(__a_unused struct sched *s, struct task *t) return; } again: - ib = fc->inbuf; + ib = *fc->inbufp; loaded = fc->in_loaded; conv = 0; FOR_EACH_FILTER_NODE(fn, fc, i) { diff --git a/gui.c b/gui.c index 15422b96..fc2cd9a1 100644 --- a/gui.c +++ b/gui.c @@ -521,13 +521,12 @@ static void setup_signal_handling(void) para_install_sighandler(SIGCHLD); para_install_sighandler(SIGWINCH); para_install_sighandler(SIGUSR1); -// signal(SIGPIPE, SIG_IGN); - signal(SIGHUP, SIG_IGN); + para_sigaction(SIGHUP, SIG_IGN); } __noreturn static void do_exit(int ret) { - signal(SIGTERM, SIG_IGN); + para_sigaction(SIGTERM, SIG_IGN); kill(0, SIGTERM); exit(ret); } diff --git a/recv.c b/recv.c index 4f595e39..5de9c6be 100644 --- a/recv.c +++ b/recv.c @@ -95,7 +95,7 @@ int main(int argc, char *argv[]) r_opened = 1; stdout_set_defaults(&sot); - sot.buf = rn.buf; + sot.bufp = &rn.buf; sot.loaded = &rn.loaded; sot.input_error = &rn.task.error; register_task(&sot.task); diff --git a/server.c b/server.c index da55b999..9bf6c3f8 100644 --- a/server.c +++ b/server.c @@ -335,25 +335,15 @@ static void init_signal_task(void) st->task.post_select = signal_post_select; sprintf(st->task.status, "signal task"); + PARA_NOTICE_LOG("setting up signal handling\n"); st->fd = para_signal_init(); /* always successful */ - - PARA_NOTICE_LOG("setting up signal handlers\n"); - if (para_install_sighandler(SIGINT) < 0) - goto err; - if (para_install_sighandler(SIGTERM) < 0) - goto err; - if (para_install_sighandler(SIGHUP) < 0) - goto err; - if (para_install_sighandler(SIGCHLD) < 0) - goto err; - if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) - goto err; + para_install_sighandler(SIGINT); + para_install_sighandler(SIGTERM); + para_install_sighandler(SIGHUP); + para_install_sighandler(SIGCHLD); + para_sigaction(SIGPIPE, SIG_IGN); add_close_on_fork_list(st->fd); register_task(&st->task); - return; -err: - PARA_EMERG_LOG("could not install signal handlers\n"); - exit(EXIT_FAILURE); } static void command_pre_select(struct sched *s, struct task *t) @@ -546,19 +536,13 @@ static void server_init(int argc, char **argv) * before the child gets a chance to ignore this signal -- only the * good die young. */ - if (signal(SIGUSR1, SIG_IGN) == SIG_ERR) { - PARA_EMERG_LOG("failed to ignore SIGUSR1\n"); - exit(EXIT_FAILURE); - } + para_sigaction(SIGUSR1, SIG_IGN); /* * We have to install a SIGCHLD handler before the afs process is being * forked off. Otherwise, para_server does not notice if afs dies before * the SIGCHLD handler has been installed by init_signal_task() below. */ - if (signal(SIGCHLD, tmp_sigchld_handler) == SIG_ERR) { - PARA_EMERG_LOG("failed to install temporary SIGCHLD handler\n"); - exit(EXIT_FAILURE); - } + para_sigaction(SIGCHLD, tmp_sigchld_handler); PARA_NOTICE_LOG("initializing the audio file selector\n"); afs_socket = init_afs(); init_signal_task(); diff --git a/signal.c b/signal.c index acc87802..59a0d45a 100644 --- a/signal.c +++ b/signal.c @@ -117,20 +117,49 @@ void para_reap_children(void) } /** - * Wrapper around signal(2). + * Install the given handler for the given signal. * * \param sig The number of the signal to catch. + * \param handler to be installed, \p SIG_IGN, or \p SIG_DFL. * - * This installs the generic signal handler for the given signal. + * This either succeeds or calls exit(EXIT_FAILURE). * - * \return This function returns 1 on success and \p -E_SIGNAL_SIG_ERR on errors. - * - * \sa signal(2). + * \sa sigaction(2). */ -int para_install_sighandler(int sig) +void para_sigaction(int sig, void (*handler)(int)) { + struct sigaction act; + PARA_DEBUG_LOG("catching signal %d\n", sig); - return signal(sig, &generic_signal_handler) == SIG_ERR? -E_SIGNAL_SIG_ERR : 1; + act.sa_handler = handler; + sigemptyset(&act.sa_mask); + act.sa_flags = 0; + if (sig == SIGALRM) { + #ifdef SA_INTERRUPT /* SunOS */ + act.sa_flags |= SA_INTERRUPT; + #endif + } else { + #ifdef SA_RESTART /* BSD */ + act.sa_flags |= SA_RESTART; + #endif + } + if (sigaction(sig, &act, NULL) >= 0) + return; + PARA_EMERG_LOG("failed to install signal handler for signal %d\n", + sig); + exit(EXIT_FAILURE); +} + +/** + * Install the generic signal handler for the given signal number. + * + * \param sig The number of the signal to catch. + * + * \sa signal(2), sigaction(2). + */ +void para_install_sighandler(int sig) +{ + para_sigaction(sig, &generic_signal_handler); } /** diff --git a/signal.h b/signal.h index 962e074a..685654d5 100644 --- a/signal.h +++ b/signal.h @@ -19,7 +19,8 @@ struct signal_task { }; int para_signal_init(void); -int para_install_sighandler(int); +void para_sigaction(int sig, void (*handler)(int)); +void para_install_sighandler(int); void para_reap_children(void); int para_reap_child(pid_t *pid); int para_next_signal(void); diff --git a/stdout.c b/stdout.c index ce0d2209..e178fe0e 100644 --- a/stdout.c +++ b/stdout.c @@ -68,14 +68,14 @@ static void stdout_post_select(struct sched *s, struct task *t) } if (!FD_ISSET(STDOUT_FILENO, &s->wfds)) return; - ret = write(STDOUT_FILENO, sot->buf, *sot->loaded); + ret = write(STDOUT_FILENO, *sot->bufp, *sot->loaded); if (ret < 0) { t->error = -ERRNO_TO_PARA_ERROR(errno); return; } *sot->loaded -= ret; if (*sot->loaded) - memmove(sot->buf, sot->buf + ret, *sot->loaded); + memmove(*sot->bufp, *sot->bufp + ret, *sot->loaded); } /** diff --git a/stdout.h b/stdout.h index 4149dad3..cca12e5f 100644 --- a/stdout.h +++ b/stdout.h @@ -10,8 +10,8 @@ * The task structure used for writing to stdout. */ struct stdout_task { - /** Pointer to the data buffer. */ - char *buf; + /** Pointer to the data buffer pointer. */ + char **bufp; /** Number of bytes loaded in \a buf. */ size_t *loaded; /** Pointer to the error variable of the feeding task. */ diff --git a/write.c b/write.c index c5a26565..cc1f716f 100644 --- a/write.c +++ b/write.c @@ -214,7 +214,7 @@ int main(int argc, char *argv[]) sit.bufsize = conf.bufsize_arg * 1024; sit.buf = para_malloc(sit.bufsize); - wng->buf = sit.buf; + wng->bufp = &sit.buf; wng->loaded = &sit.loaded; wng->input_error = &sit.task.error; diff --git a/write.h b/write.h index 71938a9c..365c237b 100644 --- a/write.h +++ b/write.h @@ -96,7 +96,7 @@ struct writer_node_group { /** Non-zero if an error or end of file was encountered by the feeding task. */ int *input_error; /** Current output buffer. */ - char *buf; + char **bufp; /** Number of bytes loaded in the output buffer. */ size_t *loaded; /** Number of audio channels of the current stream. */ diff --git a/write_common.c b/write_common.c index 4e81f62d..dcf7bb16 100644 --- a/write_common.c +++ b/write_common.c @@ -61,7 +61,7 @@ static void wng_post_select(struct sched *s, struct task *t) } if (*g->loaded && min_written) { // PARA_INFO_LOG("moving %zd bytes\n", *g->loaded); - memmove(g->buf, g->buf + min_written, *g->loaded); + memmove(*g->bufp, *g->bufp + min_written, *g->loaded); } }