summaryrefslogtreecommitdiff
path: root/main/channel.c
diff options
context:
space:
mode:
Diffstat (limited to 'main/channel.c')
-rw-r--r--main/channel.c27
1 files changed, 18 insertions, 9 deletions
diff --git a/main/channel.c b/main/channel.c
index 5e8178358..1e7bc563e 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -825,7 +825,12 @@ __ast_channel_alloc_ap(int needqueue, int state, const char *cid_num, const char
ast_channel_stage_snapshot(tmp);
if (!(nativeformats = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
- /* format capabilities structure allocation failure */
+ /*
+ * Aborting the channel creation. We do not need to complete staging
+ * the channel snapshot because the channel has not been finalized or
+ * linked into the channels container yet. Nobody else knows about
+ * this channel nor will anybody ever know about it.
+ */
return ast_channel_unref(tmp);
}
ast_format_cap_append(nativeformats, ast_format_none, 0);
@@ -851,6 +856,7 @@ __ast_channel_alloc_ap(int needqueue, int state, const char *cid_num, const char
if (!(schedctx = ast_sched_context_create())) {
ast_log(LOG_WARNING, "Channel allocation failed: Unable to create schedule context\n");
+ /* See earlier channel creation abort comment above. */
return ast_channel_unref(tmp);
}
ast_channel_sched_set(tmp, schedctx);
@@ -865,6 +871,7 @@ __ast_channel_alloc_ap(int needqueue, int state, const char *cid_num, const char
ast_channel_caller(tmp)->id.name.valid = 1;
ast_channel_caller(tmp)->id.name.str = ast_strdup(cid_name);
if (!ast_channel_caller(tmp)->id.name.str) {
+ /* See earlier channel creation abort comment above. */
return ast_channel_unref(tmp);
}
}
@@ -872,6 +879,7 @@ __ast_channel_alloc_ap(int needqueue, int state, const char *cid_num, const char
ast_channel_caller(tmp)->id.number.valid = 1;
ast_channel_caller(tmp)->id.number.str = ast_strdup(cid_num);
if (!ast_channel_caller(tmp)->id.number.str) {
+ /* See earlier channel creation abort comment above. */
return ast_channel_unref(tmp);
}
}
@@ -885,6 +893,7 @@ __ast_channel_alloc_ap(int needqueue, int state, const char *cid_num, const char
}
if (needqueue && ast_channel_internal_alertpipe_init(tmp)) {
+ /* See earlier channel creation abort comment above. */
return ast_channel_unref(tmp);
}
@@ -981,20 +990,14 @@ __ast_channel_alloc_ap(int needqueue, int state, const char *cid_num, const char
if (assignedids && (does_id_conflict(assignedids->uniqueid) || does_id_conflict(assignedids->uniqueid2))) {
ast_channel_internal_errno_set(AST_CHANNEL_ERROR_ID_EXISTS);
ao2_unlock(channels);
- /* This is a bit unorthodox, but we can't just call ast_channel_stage_snapshot_done()
- * because that will result in attempting to publish the channel snapshot. That causes
- * badness in some places, such as CDRs. So we need to manually clear the flag on the
- * channel that says that a snapshot is being cleared.
- */
- ast_clear_flag(ast_channel_flags(tmp), AST_FLAG_SNAPSHOT_STAGE);
ast_channel_unlock(tmp);
+ /* See earlier channel creation abort comment above. */
return ast_channel_unref(tmp);
}
+ /* Finalize and link into the channels container. */
ast_channel_internal_finalize(tmp);
-
ast_atomic_fetchadd_int(&chancount, +1);
-
ao2_link_flags(channels, tmp, OBJ_NOLOCK);
ao2_unlock(channels);
@@ -3137,7 +3140,9 @@ struct ast_channel *ast_waitfor_nandfds(struct ast_channel **c, int n, int *fds,
fdmap[max].chan = x; /* channel x is linked to this pfds */
max += ast_add_fd(&pfds[max], ast_channel_fd(c[x], y));
}
+ ast_channel_lock(c[x]);
CHECK_BLOCKING(c[x]);
+ ast_channel_unlock(c[x]);
}
/* Add the individual fds */
for (x = 0; x < nfds; x++) {
@@ -3164,7 +3169,9 @@ struct ast_channel *ast_waitfor_nandfds(struct ast_channel **c, int n, int *fds,
res = ast_poll(pfds, max, rms);
}
for (x = 0; x < n; x++) {
+ ast_channel_lock(c[x]);
ast_clear_flag(ast_channel_flags(c[x]), AST_FLAG_BLOCKING);
+ ast_channel_unlock(c[x]);
}
if (res < 0) { /* Simulate a timeout if we were interrupted */
if (errno != EINTR) {
@@ -3200,12 +3207,14 @@ struct ast_channel *ast_waitfor_nandfds(struct ast_channel **c, int n, int *fds,
}
if (fdmap[x].chan >= 0) { /* this is a channel */
winner = c[fdmap[x].chan]; /* override previous winners */
+ ast_channel_lock(winner);
if (res & POLLPRI) {
ast_set_flag(ast_channel_flags(winner), AST_FLAG_EXCEPTION);
} else {
ast_clear_flag(ast_channel_flags(winner), AST_FLAG_EXCEPTION);
}
ast_channel_fdno_set(winner, fdmap[x].fdno);
+ ast_channel_unlock(winner);
} else { /* this is an fd */
if (outfd) {
*outfd = pfds[x].fd;