/* A simple, thread-safe puts() work-alike */
static void write_err(const char *p) {
- pa_loop_write(2, p, strlen(p));
+ pa_loop_write(2, p, strlen(p), NULL);
}
/* The signal handler, called on every SIGXCPU */
static void callback(pa_mainloop_api*m, pa_io_event*e, int fd, pa_io_event_flags_t f, void *userdata) {
char c;
assert(m && e && f == PA_IO_EVENT_INPUT && e == io_event && fd == the_pipe[0]);
- read(the_pipe[0], &c, sizeof(c));
+ pa_read(the_pipe[0], &c, sizeof(c), NULL);
m->quit(m, 1); /* Quit the main loop */
}
close(daemon_pipe[1]);
daemon_pipe[1] = -1;
- if (pa_loop_read(daemon_pipe[0], &retval, sizeof(retval)) != sizeof(retval)) {
+ if (pa_loop_read(daemon_pipe[0], &retval, sizeof(retval), NULL) != sizeof(retval)) {
pa_log(__FILE__": read() failed: %s", pa_cstrerror(errno));
retval = 1;
}
pa_log(__FILE__": pa_pid_file_create() failed.");
#ifdef HAVE_FORK
if (conf->daemonize)
- pa_loop_write(daemon_pipe[1], &retval, sizeof(retval));
+ pa_loop_write(daemon_pipe[1], &retval, sizeof(retval), NULL);
#endif
goto finish;
}
pa_log(__FILE__": failed to initialize daemon.");
#ifdef HAVE_FORK
if (conf->daemonize)
- pa_loop_write(daemon_pipe[1], &retval, sizeof(retval));
+ pa_loop_write(daemon_pipe[1], &retval, sizeof(retval), NULL);
#endif
} else if (!c->modules || pa_idxset_size(c->modules) == 0) {
pa_log(__FILE__": daemon startup without any loaded modules, refusing to work.");
#ifdef HAVE_FORK
if (conf->daemonize)
- pa_loop_write(daemon_pipe[1], &retval, sizeof(retval));
+ pa_loop_write(daemon_pipe[1], &retval, sizeof(retval), NULL);
#endif
} else {
retval = 0;
#ifdef HAVE_FORK
if (conf->daemonize)
- pa_loop_write(daemon_pipe[1], &retval, sizeof(retval));
+ pa_loop_write(daemon_pipe[1], &retval, sizeof(retval), NULL);
#endif
c->disallow_module_loading = conf->disallow_module_loading;
goto finish;
}
- if (pa_loop_write(fd, &x, sizeof(x)) != sizeof(x))
+ if (pa_loop_write(fd, &x, sizeof(x), NULL) != sizeof(x))
pa_log(__FILE__": WARNING: write(%u, 1, 1) failed: %s", fd, pa_cstrerror(errno));
close(fd);
jack_nframes_t frames_requested;
int quit_requested;
+ int pipe_fd_type;
int pipe_fds[2];
pa_io_event *io_event;
assert(u);
assert(u->pipe_fds[0] == fd);
- read(fd, &x, 1);
+ pa_read(fd, &x, 1, &u->pipe_fd_type);
if (u->quit_requested) {
stop_sink(u);
assert(u);
assert(u->pipe_fds[1] >= 0);
- write(u->pipe_fds[1], &c, 1);
+ pa_write(u->pipe_fds[1], &c, 1, &u->pipe_fd_type);
}
static void jack_shutdown(void *arg) {
u->core = c;
u->module = m;
u->pipe_fds[0] = u->pipe_fds[1] = -1;
+ u->pipe_fd_type = 0;
pthread_mutex_init(&u->mutex, NULL);
pthread_cond_init(&u->cond, NULL);
int quit_requested;
int pipe_fds[2];
+ int pipe_fd_type;
pa_io_event *io_event;
jack_nframes_t frames_in_buffer;
assert(u);
assert(u->pipe_fds[0] == fd);
- read(fd, &x, 1);
+ pa_read(fd, &x, 1, &u->pipe_fd_type);
if (u->quit_requested) {
stop_source(u);
assert(u);
assert(u->pipe_fds[1] >= 0);
- write(u->pipe_fds[1], &c, 1);
+ pa_write(u->pipe_fds[1], &c, 1, &u->pipe_fd_type);
}
static void jack_shutdown(void *arg) {
u->core = c;
u->module = m;
u->pipe_fds[0] = u->pipe_fds[1] = -1;
+ u->pipe_fd_type = 0;
pthread_mutex_init(&u->mutex, NULL);
pthread_cond_init(&u->cond, NULL);
};
struct userdata {
- int fd;
+ int fd, fd_type;
pa_io_event *io;
char *sink_name;
pa_module *module;
if (events & PA_IO_EVENT_INPUT) {
struct input_event ev;
- if (pa_loop_read(u->fd, &ev, sizeof(ev)) <= 0) {
+ if (pa_loop_read(u->fd, &ev, sizeof(ev), &u->fd_type) <= 0) {
pa_log(__FILE__": failed to read from event device: %s", pa_cstrerror(errno));
goto fail;
}
u->io = NULL;
u->sink_name = pa_xstrdup(pa_modargs_get_value(ma, "sink", NULL));
u->fd = -1;
+ u->fd_type = 0;
if ((u->fd = open(pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), O_RDONLY)) < 0) {
pa_log(__FILE__": failed to open evdev device: %s", pa_cstrerror(errno));
*/
if (u->source) {
char *buf = pa_xnew(char, u->sample_size);
- read(u->fd, buf, u->sample_size);
+ pa_read(u->fd, buf, u->sample_size, NULL);
pa_xfree(buf);
}
#ifndef HAVE_SIGACTION
signal(sig, signal_handler);
#endif
- pa_write(signal_pipe[1], &sig, sizeof(sig));
+ pa_write(signal_pipe[1], &sig, sizeof(sig), NULL);
}
static void dispatch(pa_mainloop_api*a, int sig) {
int sig;
assert(a && e && f == PA_IO_EVENT_INPUT && e == io_event && fd == signal_pipe[0]);
- if ((r = pa_read(signal_pipe[0], &sig, sizeof(sig))) < 0) {
+ if ((r = pa_read(signal_pipe[0], &sig, sizeof(sig), NULL)) < 0) {
if (errno == EAGAIN)
return;
int deferred_pending;
int wakeup_pipe[2];
+ int wakeup_pipe_type;
enum {
STATE_PASSIVE,
m = pa_xmalloc(sizeof(pa_mainloop));
+ m->wakeup_pipe_type = 0;
if (pipe(m->wakeup_pipe) < 0) {
pa_log_error(__FILE__": ERROR: cannot create wakeup pipe");
pa_xfree(m);
assert(m);
if (m->wakeup_pipe[1] >= 0)
- pa_write(m->wakeup_pipe[1], &c, sizeof(c));
+ pa_write(m->wakeup_pipe[1], &c, sizeof(c), &m->wakeup_pipe_type);
}
static void clear_wakeup(pa_mainloop *m) {
if (m->wakeup_pipe[0] < 0)
return;
- while (pa_read(m->wakeup_pipe[0], &c, sizeof(c)) == sizeof(c));
+ while (pa_read(m->wakeup_pipe[0], &c, sizeof(c), &m->wakeup_pipe_type) == sizeof(c));
}
int pa_mainloop_prepare(pa_mainloop *m, int timeout) {
* exits */
static void oom(void) {
static const char e[] = "Not enough memory\n";
- pa_loop_write(STDERR_FILENO, e, sizeof(e)-1);
+ pa_loop_write(STDERR_FILENO, e, sizeof(e)-1, NULL);
#ifdef SIGQUIT
raise(SIGQUIT);
#endif
lseek(fd, 0, SEEK_SET);
ftruncate(fd, 0);
- if ((r = pa_loop_write(fd, ret_data, length)) < 0 || (size_t) r != length) {
+ if ((r = pa_loop_write(fd, ret_data, length, NULL)) < 0 || (size_t) r != length) {
pa_log(__FILE__": failed to write cookie file: %s", pa_cstrerror(errno));
return -1;
}
unlock = pa_lock_fd(fd, 1) >= 0;
- if ((r = pa_loop_read(fd, data, length)) < 0) {
+ if ((r = pa_loop_read(fd, data, length, NULL)) < 0) {
pa_log(__FILE__": failed to read cookie file '%s': %s", fn, pa_cstrerror(errno));
goto finish;
}
unlock = pa_lock_fd(fd, 1) >= 0;
- if ((r = pa_loop_write(fd, data, length)) < 0 || (size_t) r != length) {
+ if ((r = pa_loop_write(fd, data, length, NULL)) < 0 || (size_t) r != length) {
pa_log(__FILE__": failed to read cookie file '%s': %s", fn, pa_cstrerror(errno));
goto finish;
}
return ret;
}
-/** Platform independent read function. Necessary since not all systems
- * treat all file descriptors equal. */
-ssize_t pa_read(int fd, void *buf, size_t count) {
- ssize_t r;
+/** Platform independent read function. Necessary since not all
+ * systems treat all file descriptors equal. If type is
+ * non-NULL it is used to cache the type of the fd. This is
+ * useful for making sure that only a single syscall is executed per
+ * function call. The variable pointed to should be initialized to 0
+ * by the caller. */
+ssize_t pa_read(int fd, void *buf, size_t count, int *type) {
#ifdef OS_IS_WIN32
- r = recv(fd, buf, count, 0);
- if (r < 0) {
+
+ if (!type || *type == 0) {
+ ssize_t r;
+
+ if ((r = recv(fd, buf, count, 0)) >= 0)
+ return r;
+
if (WSAGetLastError() != WSAENOTSOCK) {
errno = WSAGetLastError();
return r;
}
+
+ if (type)
+ *type = 1;
}
- if (r < 0)
#endif
- r = read(fd, buf, count);
-
- return r;
+
+ return read(fd, buf, count);
}
/** Similar to pa_read(), but handles writes */
-ssize_t pa_write(int fd, const void *buf, size_t count) {
- ssize_t r;
+ssize_t pa_write(int fd, const void *buf, size_t count, int *type) {
+
+ if (!type || *type == 0) {
+ ssize_t r;
+ if ((r = send(fd, buf, count, MSG_NOSIGNAL)) >= 0)
+ return r;
+
#ifdef OS_IS_WIN32
- r = send(fd, buf, count, 0);
- if (r < 0) {
if (WSAGetLastError() != WSAENOTSOCK) {
errno = WSAGetLastError();
return r;
}
- }
-
- if (r < 0)
+#else
+ if (errno != ENOTSOCK)
+ return r;
#endif
- r = write(fd, buf, count);
- return r;
+ if (type)
+ *type = 1;
+ }
+
+ return write(fd, buf, count);
}
/** Calls read() in a loop. Makes sure that as much as 'size' bytes,
* unless EOF is reached or an error occured */
-ssize_t pa_loop_read(int fd, void*data, size_t size) {
+ssize_t pa_loop_read(int fd, void*data, size_t size, int *type) {
ssize_t ret = 0;
- assert(fd >= 0 && data && size);
+ int _type;
+
+ assert(fd >= 0);
+ assert(data);
+ assert(size);
+
+ if (!type) {
+ _type = 0;
+ type = &_type;
+ }
while (size > 0) {
ssize_t r;
- if ((r = pa_read(fd, data, size)) < 0)
+ if ((r = pa_read(fd, data, size, type)) < 0)
return r;
if (r == 0)
}
/** Similar to pa_loop_read(), but wraps write() */
-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, int *type) {
ssize_t ret = 0;
- assert(fd >= 0 && data && size);
+ int _type;
+
+ assert(fd >= 0);
+ assert(data);
+ assert(size);
+
+ if (!type) {
+ _type = 0;
+ type = &_type;
+ }
while (size > 0) {
ssize_t r;
- if ((r = pa_write(fd, data, size)) < 0)
+ if ((r = pa_write(fd, data, size, type)) < 0)
return r;
if (r == 0)
int pa_make_secure_dir(const char* dir);
int pa_make_secure_parent_dir(const char *fn);
-ssize_t pa_read(int fd, void *buf, size_t count);
-ssize_t pa_write(int fd, const void *buf, size_t count);
-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_read(int fd, void *buf, size_t count, int *type);
+ssize_t pa_write(int fd, const void *buf, size_t count, int *type);
+ssize_t pa_loop_read(int fd, void*data, size_t size, int *type);
+ssize_t pa_loop_write(int fd, const void*data, size_t size, int *type);
void pa_check_signal_is_blocked(int sig);
struct pa_iochannel {
int ifd, ofd;
+ int ifd_type, ofd_type;
pa_mainloop_api* mainloop;
pa_iochannel_cb_t callback;
io = pa_xnew(pa_iochannel, 1);
io->ifd = ifd;
io->ofd = ofd;
+ io->ifd_type = io->ofd_type = 0;
io->mainloop = m;
io->userdata = NULL;
assert(l);
assert(io->ofd >= 0);
- r = pa_write(io->ofd, data, l);
+ r = pa_write(io->ofd, data, l, &io->ofd_type);
if (r >= 0) {
io->writable = 0;
enable_mainloop_sources(io);
assert(data);
assert(io->ifd >= 0);
- r = pa_read(io->ifd, data, l);
+ r = pa_read(io->ifd, data, l, &io->ifd_type);
if (r >= 0) {
io->readable = 0;
enable_mainloop_sources(io);
assert(fn && fd >= 0);
- if ((r = pa_loop_read(fd, t, sizeof(t)-1)) < 0) {
+ if ((r = pa_loop_read(fd, t, sizeof(t)-1, NULL)) < 0) {
pa_log_warn(__FILE__": WARNING: failed to read PID file '%s': %s",
fn, pa_cstrerror(errno));
return (pid_t) -1;
snprintf(t, sizeof(t), "%lu\n", (unsigned long) getpid());
l = strlen(t);
- if (pa_loop_write(fd, t, l) != (ssize_t) l) {
+ if (pa_loop_write(fd, t, l, NULL) != (ssize_t) l) {
pa_log(__FILE__": failed to write PID file.");
goto fail;
}
if ((fd = open(*device, O_RDONLY)) >= 0) {
- if ((r = pa_loop_read(fd, ret_data, length)) < 0 || (size_t) r != length)
+ if ((r = pa_loop_read(fd, ret_data, length, NULL)) < 0 || (size_t) r != length)
ret = -1;
close(fd);
if (pa_mcalign_pop(a, &t) < 0)
break;
- pa_loop_write(STDOUT_FILENO, (uint8_t*) t.memblock->data + t.index, t.length);
+ pa_loop_write(STDOUT_FILENO, (uint8_t*) t.memblock->data + t.index, t.length, NULL);
fprintf(stderr, "Wrote %lu bytes.\n", (unsigned long) t.length);
pa_memblock_unref(t.memblock);