if (softmix_data->timer) {
ast_timer_close(softmix_data->timer);
+ softmix_data->timer = NULL;
}
}
softmix_translate_helper_cleanup(&trans_helper);
/* Wait for the timing source to tell us to wake up and get things done */
ast_waitfor_n_fd(&timingfd, 1, &timeout, NULL);
- ast_timer_ack(timer, 1);
+ if (ast_timer_ack(timer, 1) < 0) {
+ ast_log(LOG_ERROR, "Failed to acknowledge timer in softmix bridge\n");
+ ao2_lock(bridge);
+ goto softmix_cleanup;
+ }
ao2_lock(bridge);
/* make sure to detect mixing interval changes if they occur. */
if (iaxtrunkdebug)
ast_verbose("Beginning trunk processing. Trunk queue ceiling is %d bytes per host\n", trunkmaxsize);
- if (timer) {
- ast_timer_ack(timer, 1);
+ if (timer) {
+ if (ast_timer_ack(timer, 1) < 0) {
+ ast_log(LOG_ERROR, "Timer failed acknowledge\n");
+ return 0;
+ }
}
/* For each peer that supports trunking... */
/* Wake up once a second just in case SIGURG was sent while
* we weren't in poll(), to make sure we don't hang when trying
* to unload. */
- ast_io_wait(io, 1000);
+ if (ast_io_wait(io, 1000) <= 0) {
+ break;
+ }
}
return NULL;
ao2_ref(callno_pool_trunk, -1);
if (timer) {
ast_timer_close(timer);
+ timer = NULL;
}
transmit_processor = ast_taskprocessor_unreference(transmit_processor);
ast_sched_context_destroy(sched);
if (set_config(config, 0, 0) == -1) {
if (timer) {
ast_timer_close(timer);
+ timer = NULL;
}
return AST_MODULE_LOAD_DECLINE;
}
}
if (ast_channel_fdno(chan) == AST_JITTERBUFFER_FD && framedata->timer) {
- ast_timer_ack(framedata->timer, 1);
+ if (ast_timer_ack(framedata->timer, 1) < 0) {
+ ast_log(LOG_ERROR, "Failed to acknowledge timer in jitter buffer\n");
+ return frame;
+ }
}
if (!frame) {
int (*timer_open)(void);
void (*timer_close)(int handle);
int (*timer_set_rate)(int handle, unsigned int rate);
- void (*timer_ack)(int handle, unsigned int quantity);
+ int (*timer_ack)(int handle, unsigned int quantity);
int (*timer_enable_continuous)(int handle);
int (*timer_disable_continuous)(int handle);
enum ast_timer_event (*timer_get_event)(int handle);
* \note This function should only be called if timer_get_event()
* returned AST_TIMING_EVENT_EXPIRED.
*
- * \return nothing
- * \since 1.6.1
+ * \retval -1 failure, with errno set
+ * \retval 0 success
+ * \since 10.5.2
*/
-void ast_timer_ack(const struct ast_timer *handle, unsigned int quantity);
+int ast_timer_ack(const struct ast_timer *handle, unsigned int quantity);
/*!
* \brief Enable continuous mode
ast_channel_internal_alertpipe_close(chan);
if (ast_channel_timer(chan)) {
ast_timer_close(ast_channel_timer(chan));
+ ast_channel_timer_set(chan, NULL);
}
#ifdef HAVE_EPOLL
for (i = 0; i < AST_MAX_FDS; i++) {
switch (res) {
case AST_TIMING_EVENT_EXPIRED:
- ast_timer_ack(ast_channel_timer(chan), 1);
+ if (ast_timer_ack(ast_channel_timer(chan), 1) < 0) {
+ ast_log(LOG_ERROR, "Failed to acknoweldge timer in ast_read\n");
+ goto done;
+ }
if (ast_channel_timingfunc(chan)) {
/* save a copy of func/data before unlocking the channel */
void ast_timer_close(struct ast_timer *handle)
{
handle->holder->iface->timer_close(handle->fd);
+ handle->fd = -1;
ast_module_unref(handle->holder->mod);
ast_free(handle);
}
return res;
}
-void ast_timer_ack(const struct ast_timer *handle, unsigned int quantity)
+int ast_timer_ack(const struct ast_timer *handle, unsigned int quantity)
{
- handle->holder->iface->timer_ack(handle->fd, quantity);
+ int res = -1;
+
+ res = handle->holder->iface->timer_ack(handle->fd, quantity);
+
+ return res;
}
int ast_timer_enable_continuous(const struct ast_timer *handle)
if (res == 1) {
count++;
- ast_timer_ack(timer, 1);
+ if (ast_timer_ack(timer, 1) < 0) {
+ ast_cli(a->fd, "Timer failed to acknowledge.\n");
+ ast_timer_close(timer);
+ return CLI_FAILURE;
+ }
} else if (!res) {
ast_cli(a->fd, "poll() timed out! This is bad.\n");
} else if (errno != EAGAIN && errno != EINTR) {
}
ast_timer_close(timer);
+ timer = NULL;
ast_cli(a->fd, "It has been %" PRIi64 " milliseconds, and we got %d timer ticks\n",
ast_tvdiff_ms(end, start), count);
p->isdone = 1;
ast_timer_close(p->timer);
-
+ p->timer = NULL;
fax_release(&p->fax_state);
t38_terminal_release(&p->t38_state);
struct ast_frame *f = &fax_frame;
ast_format_set(&fax_frame.subclass.format, AST_FORMAT_SLINEAR, 0);
- ast_timer_ack(p->timer, 1);
+ if (ast_timer_ack(p->timer, 1) < 0) {
+ ast_log(LOG_ERROR, "Failed to acknowledge timer for FAX session '%d'\n", s->id);
+ return NULL;
+ }
/* XXX do we need to lock here? */
if (p->isdone) {
#endif
/* Pause some amount of time */
if (ast_poll(&pfd, 1, -1) > 0) {
- ast_timer_ack(class->timer, 1);
+ if (ast_timer_ack(class->timer, 1) < 0) {
+ ast_log(LOG_ERROR, "Failed to acknowledge timer for mp3player\n");
+ return NULL;
+ }
res = 320;
} else {
ast_log(LOG_WARNING, "poll() failed: %s\n", strerror(errno));
static int dahdi_timer_open(void);
static void dahdi_timer_close(int handle);
static int dahdi_timer_set_rate(int handle, unsigned int rate);
-static void dahdi_timer_ack(int handle, unsigned int quantity);
+static int dahdi_timer_ack(int handle, unsigned int quantity);
static int dahdi_timer_enable_continuous(int handle);
static int dahdi_timer_disable_continuous(int handle);
static enum ast_timer_event dahdi_timer_get_event(int handle);
return 0;
}
-static void dahdi_timer_ack(int handle, unsigned int quantity)
+static int dahdi_timer_ack(int handle, unsigned int quantity)
{
- ioctl(handle, DAHDI_TIMERACK, &quantity);
+ return ioctl(handle, DAHDI_TIMERACK, &quantity) ? -1 : 0;
}
static int dahdi_timer_enable_continuous(int handle)
static int kqueue_timer_open(void);
static void kqueue_timer_close(int handle);
static int kqueue_timer_set_rate(int handle, unsigned int rate);
-static void kqueue_timer_ack(int handle, unsigned int quantity);
+static int kqueue_timer_ack(int handle, unsigned int quantity);
static int kqueue_timer_enable_continuous(int handle);
static int kqueue_timer_disable_continuous(int handle);
static enum ast_timer_event kqueue_timer_get_event(int handle);
return 0;
}
-static void kqueue_timer_ack(int handle, unsigned int quantity)
+static int kqueue_timer_ack(int handle, unsigned int quantity)
{
struct kqueue_timer *our_timer;
if (!(our_timer = lookup_timer(handle))) {
- return;
+ return -1;
}
if (our_timer->unacked < quantity) {
ast_debug(1, "Acking more events than have expired?!!\n");
our_timer->unacked = 0;
+ ao2_ref(our_timer, -1);
+ return -1;
} else {
our_timer->unacked -= quantity;
}
+
+ ao2_ref(our_timer, -1);
+ return 0;
}
static int kqueue_timer_enable_continuous(int handle)
static int pthread_timer_open(void);
static void pthread_timer_close(int handle);
static int pthread_timer_set_rate(int handle, unsigned int rate);
-static void pthread_timer_ack(int handle, unsigned int quantity);
+static int pthread_timer_ack(int handle, unsigned int quantity);
static int pthread_timer_enable_continuous(int handle);
static int pthread_timer_disable_continuous(int handle);
static enum ast_timer_event pthread_timer_get_event(int handle);
static void pthread_timer_destructor(void *obj);
static struct pthread_timer *find_timer(int handle, int unlinkobj);
static void write_byte(struct pthread_timer *timer);
-static void read_pipe(struct pthread_timer *timer, unsigned int num);
+static int read_pipe(struct pthread_timer *timer, unsigned int num);
/*!
* \brief Data for the timing thread
return 0;
}
-static void pthread_timer_ack(int handle, unsigned int quantity)
+static int pthread_timer_ack(int handle, unsigned int quantity)
{
struct pthread_timer *timer;
+ int res;
ast_assert(quantity > 0);
if (!(timer = find_timer(handle, 0))) {
- return;
+ return -1;
}
ao2_lock(timer);
- read_pipe(timer, quantity);
+ res = read_pipe(timer, quantity);
ao2_unlock(timer);
ao2_ref(timer, -1);
+
+ return res;
}
static int pthread_timer_enable_continuous(int handle)
ao2_lock(timer);
if (timer->continuous) {
timer->continuous = 0;
- read_pipe(timer, 1);
+ if (read_pipe(timer, 1) != 0) {
+ /* Let the errno from read_pipe propagate up */
+ ao2_unlock(timer);
+ ao2_ref(timer, -1);
+ return -1;
+ }
}
ao2_unlock(timer);
/*!
* \internal
* \pre timer is locked
+ * \retval 0 if nothing to read or read success
+ * \retval -1 on error
*/
-static void read_pipe(struct pthread_timer *timer, unsigned int quantity)
+static int read_pipe(struct pthread_timer *timer, unsigned int quantity)
{
int rd_fd = timer->pipe[PIPE_READ];
int pending_ticks = timer->pending_ticks;
}
if (!quantity) {
- return;
+ return 0;
}
do {
if (ast_poll(&pfd, 1, 0) != 1) {
ast_debug(1, "Reading not available on timing pipe, "
"quantity: %u\n", quantity);
- break;
+ return -1;
}
res = read(rd_fd, buf,
}
ast_log(LOG_ERROR, "read failed on timing pipe: %s\n",
strerror(errno));
- break;
+ return -1;
}
quantity -= res;
timer->pending_ticks -= res;
} while (quantity);
+
+ return 0;
}
/*!
static int timerfd_timer_open(void);
static void timerfd_timer_close(int handle);
static int timerfd_timer_set_rate(int handle, unsigned int rate);
-static void timerfd_timer_ack(int handle, unsigned int quantity);
+static int timerfd_timer_ack(int handle, unsigned int quantity);
static int timerfd_timer_enable_continuous(int handle);
static int timerfd_timer_disable_continuous(int handle);
static enum ast_timer_event timerfd_timer_get_event(int handle);
{
struct timerfd_timer *timer = obj;
close(timer->handle);
+ timer->handle = -1;
}
static int timerfd_timer_open(void)
.handle = handle,
};
+ if (handle == -1) {
+ ast_log(LOG_ERROR, "Attempting to close timerfd handle -1");
+ return;
+ }
+
if (!(our_timer = ao2_find(timerfd_timers, &find_helper, OBJ_POINTER))) {
ast_log(LOG_ERROR, "Couldn't find timer with handle %d\n", handle);
return;
};
int res = 0;
+ if (handle == -1) {
+ ast_log(LOG_ERROR, "Attempting to set rate on timerfd handle -1");
+ return -1;
+ }
+
if (!(our_timer = ao2_find(timerfd_timers, &find_helper, OBJ_POINTER))) {
ast_log(LOG_ERROR, "Couldn't find timer with handle %d\n", handle);
return -1;
return res;
}
-static void timerfd_timer_ack(int handle, unsigned int quantity)
+static int timerfd_timer_ack(int handle, unsigned int quantity)
{
uint64_t expirations;
int read_result = 0;
+ int res = 0;
struct timerfd_timer *our_timer, find_helper = {
.handle = handle,
};
+ if (handle == -1) {
+ ast_log(LOG_ERROR, "Attempting to ack timerfd handle -1");
+ return -1;
+ }
+
if (!(our_timer = ao2_find(timerfd_timers, &find_helper, OBJ_POINTER))) {
ast_log(LOG_ERROR, "Couldn't find a timer with handle %d\n", handle);
- return;
+ return -1;
}
ao2_lock(our_timer);
struct itimerspec timer_status;
if (timerfd_gettime(handle, &timer_status)) {
- ast_log(LOG_ERROR, "Call to timerfd_gettime() error: %s\n", strerror(errno));
+ ast_log(LOG_ERROR, "Call to timerfd_gettime() using handle %d error: %s\n", handle, strerror(errno));
expirations = 0;
+ res = -1;
break;
}
continue;
} else {
ast_log(LOG_ERROR, "Read error: %s\n", strerror(errno));
+ res = -1;
break;
}
}
if (expirations != quantity) {
ast_debug(2, "Expected to acknowledge %u ticks but got %llu instead\n", quantity, (unsigned long long) expirations);
}
+ return res;
}
static int timerfd_timer_enable_continuous(int handle)
.handle = handle,
};
+ if (handle == -1) {
+ ast_log(LOG_ERROR, "Attempting to enable timerfd handle -1");
+ return -1;
+ }
+
if (!(our_timer = ao2_find(timerfd_timers, &find_helper, OBJ_POINTER))) {
ast_log(LOG_ERROR, "Couldn't find timer with handle %d\n", handle);
return -1;
.handle = handle,
};
+ if (handle == -1) {
+ ast_log(LOG_ERROR, "Attempting to disable timerfd handle -1");
+ return -1;
+ }
+
if (!(our_timer = ao2_find(timerfd_timers, &find_helper, OBJ_POINTER))) {
ast_log(LOG_ERROR, "Couldn't find timer with handle %d\n", handle);
return -1;
}
ao2_lock(our_timer);
- if(!our_timer->is_continuous) {
+ if (!our_timer->is_continuous) {
/* No reason to do anything if we're not
* in continuous mode
*/
.handle = handle,
};
+ if (handle == -1) {
+ ast_log(LOG_ERROR, "Attempting to get event from timerfd handle -1");
+ return -1;
+ }
+
if (!(our_timer = ao2_find(timerfd_timers, &find_helper, OBJ_POINTER))) {
ast_log(LOG_ERROR, "Couldn't find timer with handle %d\n", handle);
return -1;