1
0
mirror of https://gitlab.xiph.org/xiph/icecast-common.git synced 2025-02-02 15:07:47 -05:00

Feature: Make all IO functions thread safe.

This commit is contained in:
Philipp Schafft 2019-06-30 09:51:49 +00:00
parent 02e0375711
commit efc054cc89

134
src/io.c
View File

@ -19,14 +19,28 @@
struct igloo_io_tag {
igloo_interface_base(io)
/* Mutex for igloo_ro_*(). */
igloo_mutex_t lock;
int touched;
#if defined(IGLOO_CTC_HAVE_SYS_SELECT_H) || defined(IGLOO_CTC_HAVE_POLL)
int fd;
#endif
};
static void __free(igloo_ro_t self)
{
igloo_io_t *io = igloo_RO_TO_TYPE(self, igloo_io_t);
igloo_thread_mutex_lock(&(io->lock));
igloo_thread_mutex_unlock(&(io->lock));
igloo_thread_mutex_destroy(&(io->lock));
igloo_interface_base_free(self);
}
igloo_RO_PUBLIC_TYPE(igloo_io_t,
igloo_RO_TYPEDECL_FREE(igloo_interface_base_free)
igloo_RO_TYPEDECL_FREE(__free)
);
@ -36,6 +50,8 @@ igloo_io_t * igloo_io_new(const igloo_io_ifdesc_t *ifdesc, igloo_ro_t backend_ob
if (!io)
return NULL;
igloo_thread_mutex_create(&(io->lock));
io->touched = 1;
return io;
@ -44,47 +60,59 @@ igloo_io_t * igloo_io_new(const igloo_io_ifdesc_t *ifdesc, igloo_ro_t backend_ob
ssize_t igloo_io_read(igloo_io_t *io, void *buffer, size_t len)
{
ssize_t ret = -1;
if (!io || !buffer)
return -1;
if (!len)
return 0;
igloo_thread_mutex_lock(&(io->lock));
io->touched = 1;
if (io->ifdesc->read)
return io->ifdesc->read(igloo_INTERFACE_BASIC_CALL(io), buffer, len);
ret = io->ifdesc->read(igloo_INTERFACE_BASIC_CALL(io), buffer, len);
igloo_thread_mutex_unlock(&(io->lock));
return -1;
return ret;
}
ssize_t igloo_io_write(igloo_io_t *io, const void *buffer, size_t len)
{
ssize_t ret = -1;
if (!io || !buffer)
return -1;
if (!len)
return 0;
igloo_thread_mutex_lock(&(io->lock));
io->touched = 1;
if (io->ifdesc->write)
return io->ifdesc->write(igloo_INTERFACE_BASIC_CALL(io), buffer, len);
ret = io->ifdesc->write(igloo_INTERFACE_BASIC_CALL(io), buffer, len);
igloo_thread_mutex_unlock(&(io->lock));
return -1;
return ret;
}
int igloo_io_flush(igloo_io_t *io, igloo_io_opflag_t flags)
{
int ret = -1;
if (!io)
return -1;
igloo_thread_mutex_lock(&(io->lock));
io->touched = 1;
if (io->ifdesc->flush)
return io->ifdesc->flush(igloo_INTERFACE_BASIC_CALL(io), flags);
ret = io->ifdesc->flush(igloo_INTERFACE_BASIC_CALL(io), flags);
igloo_thread_mutex_unlock(&(io->lock));
return -1;
return ret;
}
int igloo_io_sync(igloo_io_t *io, igloo_io_opflag_t flags)
@ -94,46 +122,59 @@ int igloo_io_sync(igloo_io_t *io, igloo_io_opflag_t flags)
if (!io)
return -1;
igloo_thread_mutex_lock(&(io->lock));
if (io->ifdesc->flush)
io->ifdesc->flush(igloo_INTERFACE_BASIC_CALL(io), flags);
if (io->ifdesc->sync) {
ret = io->ifdesc->sync(igloo_INTERFACE_BASIC_CALL(io), flags);
if (ret != 0)
if (ret != 0) {
igloo_thread_mutex_unlock(&(io->lock));
return ret;
}
io->touched = 0;
igloo_thread_mutex_unlock(&(io->lock));
return ret;
}
igloo_thread_mutex_unlock(&(io->lock));
return -1;
}
int igloo_io_set_blockingmode(igloo_io_t *io, libigloo_io_blockingmode_t mode)
{
int ret = -1;
if (!io)
return -1;
if (mode != igloo_IO_BLOCKINGMODE_NONE && mode != igloo_IO_BLOCKINGMODE_FULL)
return -1;
igloo_thread_mutex_lock(&(io->lock));
io->touched = 1;
if (io->ifdesc->set_blockingmode)
return io->ifdesc->set_blockingmode(igloo_INTERFACE_BASIC_CALL(io), mode);
ret = io->ifdesc->set_blockingmode(igloo_INTERFACE_BASIC_CALL(io), mode);
igloo_thread_mutex_unlock(&(io->lock));
return -1;
return ret;
}
libigloo_io_blockingmode_t igloo_io_get_blockingmode(igloo_io_t *io)
{
libigloo_io_blockingmode_t ret = igloo_IO_BLOCKINGMODE_ERROR;
if (!io)
return igloo_IO_BLOCKINGMODE_ERROR;
igloo_thread_mutex_lock(&(io->lock));
if (io->ifdesc->get_blockingmode)
return io->ifdesc->get_blockingmode(igloo_INTERFACE_BASIC_CALL(io));
ret = io->ifdesc->get_blockingmode(igloo_INTERFACE_BASIC_CALL(io));
igloo_thread_mutex_unlock(&(io->lock));
return igloo_IO_BLOCKINGMODE_ERROR;
return ret;
}
#ifdef IGLOO_CTC_HAVE_SYS_SELECT_H
@ -144,15 +185,24 @@ int igloo_io_select_set(igloo_io_t *io, fd_set *set, int *maxfd, igloo_io_opflag
if (!io || !set || !maxfd)
return -1;
if (!io->ifdesc->get_fd_for_systemcall)
igloo_thread_mutex_lock(&(io->lock));
if (!io->ifdesc->get_fd_for_systemcall) {
igloo_thread_mutex_unlock(&(io->lock));
return -1;
}
if (io->touched || !(flags & igloo_IO_OPFLAG_NOWRITE)) {
igloo_thread_mutex_unlock(&(io->lock));
ret = igloo_io_sync(io, igloo_IO_OPFLAG_DEFAULTS|(flags & igloo_IO_OPFLAG_NOWRITE));
if (ret != 0)
return ret;
if (io->touched)
igloo_thread_mutex_lock(&(io->lock));
if (io->touched) {
igloo_thread_mutex_unlock(&(io->lock));
return -1;
}
}
io->fd = io->ifdesc->get_fd_for_systemcall(igloo_INTERFACE_BASIC_CALL(io));
@ -163,6 +213,8 @@ int igloo_io_select_set(igloo_io_t *io, fd_set *set, int *maxfd, igloo_io_opflag
if (*maxfd < io->fd)
*maxfd = io->fd;
igloo_thread_mutex_unlock(&(io->lock));
return 0;
}
@ -171,23 +223,31 @@ int igloo_io_select_clear(igloo_io_t *io, fd_set *set)
if (!io || !set)
return -1;
if (io->touched || io->fd < 0)
igloo_thread_mutex_lock(&(io->lock));
if (io->touched || io->fd < 0) {
igloo_thread_mutex_unlock(&(io->lock));
return -1;
}
FD_CLR(io->fd, set);
igloo_thread_mutex_unlock(&(io->lock));
return 0;
}
int igloo_io_select_isset(igloo_io_t *io, fd_set *set)
{
int ret = -1;
if (!io || !set)
return -1;
if (io->touched || io->fd < 0)
return -1;
igloo_thread_mutex_lock(&(io->lock));
if (!io->touched && io->fd >= 0)
ret = FD_ISSET(io->fd, set) ? 1 : 0;
igloo_thread_mutex_unlock(&(io->lock));
return FD_ISSET(io->fd, set) ? 1 : 0;
return ret;
}
#endif
@ -208,27 +268,40 @@ int igloo_io_poll_fill(igloo_io_t *io, struct pollfd *fd, short events)
if (!io || !fd)
return -1;
if (!io->ifdesc->get_fd_for_systemcall)
return -1;
is_safe = !((events|safe_events) - safe_events);
igloo_thread_mutex_lock(&(io->lock));
if (!io->ifdesc->get_fd_for_systemcall) {
igloo_thread_mutex_unlock(&(io->lock));
return -1;
}
if (io->touched || !is_safe) {
igloo_thread_mutex_unlock(&(io->lock));
ret = igloo_io_sync(io, igloo_IO_OPFLAG_DEFAULTS|(is_safe ? 0 : igloo_IO_OPFLAG_NOWRITE));
if (ret != 0)
return ret;
if (io->touched)
igloo_thread_mutex_lock(&(io->lock));
if (io->touched) {
igloo_thread_mutex_unlock(&(io->lock));
return -1;
}
}
io->fd = io->ifdesc->get_fd_for_systemcall(igloo_INTERFACE_BASIC_CALL(io));
if (io->fd < 0)
if (io->fd < 0) {
igloo_thread_mutex_unlock(&(io->lock));
return -1;
}
memset(fd, 0, sizeof(*fd));
fd->fd = io->fd;
fd->events = events;
igloo_thread_mutex_unlock(&(io->lock));
return 0;
}
#endif
@ -236,18 +309,19 @@ int igloo_io_poll_fill(igloo_io_t *io, struct pollfd *fd, short events)
int igloo_io_control(igloo_io_t *io, igloo_io_opflag_t flags, igloo_io_control_t control, ...)
{
#ifdef IGLOO_CTC_STDC_HEADERS
int ret;
int ret = -1;
va_list ap;
if (!io)
return -1;
if (!io->ifdesc->control)
return -1;
va_start(ap, control);
ret = io->ifdesc->control(igloo_INTERFACE_BASIC_CALL(io), flags, control, ap);
va_end(ap);
igloo_thread_mutex_lock(&(io->lock));
if (io->ifdesc->control) {
va_start(ap, control);
ret = io->ifdesc->control(igloo_INTERFACE_BASIC_CALL(io), flags, control, ap);
va_end(ap);
}
igloo_thread_mutex_unlock(&(io->lock));
return ret;
#else