void ast_threadpool_shutdown(struct ast_threadpool *pool) { if (!pool) { return; } /* Shut down the taskprocessors and everything else just * takes care of itself via the taskprocessor callbacks */ ao2_lock(pool); pool->shutting_down = 1; ao2_unlock(pool); ast_taskprocessor_unreference(pool->control_tps); ast_taskprocessor_unreference(pool->tps); }
static int unload_module(void) { ast_sip_session_unregister_supplement(&messaging_supplement); ast_msg_tech_unregister(&msg_tech); ast_sip_unregister_service(&messaging_module); ast_taskprocessor_unreference(message_serializer); return 0; }
/*! * \brief Destructor. * * \internal */ static void dns_system_resolver_destroy(void) { /* Unreference the task processor */ dns_system_resolver_tp = ast_taskprocessor_unreference(dns_system_resolver_tp); /* Unregister the base resolver */ ast_dns_resolver_unregister(&dns_system_resolver_base); }
/*! * \internal * \brief Shutdown the serializers in the distributor pool. * \since 13.10.0 * * \return Nothing */ static void distributor_pool_shutdown(void) { int idx; for (idx = 0; idx < ARRAY_LEN(distributor_pool); ++idx) { ast_taskprocessor_unreference(distributor_pool[idx]); distributor_pool[idx] = NULL; } }
/*! \brief WebSocket connection handler. */ static void websocket_cb(struct ast_websocket *session, struct ast_variable *parameters, struct ast_variable *headers) { struct ast_taskprocessor *serializer; struct transport_create_data create_data; struct ws_transport *transport; struct transport_read_data read_data; if (ast_websocket_set_nonblock(session)) { ast_websocket_unref(session); return; } if (ast_websocket_set_timeout(session, get_write_timeout())) { ast_websocket_unref(session); return; } serializer = create_websocket_serializer(); if (!serializer) { ast_websocket_unref(session); return; } create_data.ws_session = session; if (ast_sip_push_task_synchronous(serializer, transport_create, &create_data)) { ast_log(LOG_ERROR, "Could not create WebSocket transport.\n"); ast_websocket_unref(session); return; } transport = create_data.transport; read_data.transport = transport; while (ast_wait_for_input(ast_websocket_fd(session), -1) > 0) { enum ast_websocket_opcode opcode; int fragmented; if (ast_websocket_read(session, &read_data.payload, &read_data.payload_len, &opcode, &fragmented)) { break; } if (opcode == AST_WEBSOCKET_OPCODE_TEXT || opcode == AST_WEBSOCKET_OPCODE_BINARY) { ast_sip_push_task_synchronous(serializer, transport_read, &read_data); } else if (opcode == AST_WEBSOCKET_OPCODE_CLOSE) { break; } } ast_sip_push_task_synchronous(serializer, transport_shutdown, transport); ast_taskprocessor_unreference(serializer); ast_websocket_unref(session); }
static void serializer_task_pushed(struct ast_taskprocessor_listener *listener, int was_empty) { if (was_empty) { struct serializer *ser = ast_taskprocessor_listener_get_user_data(listener); struct ast_taskprocessor *tps = ast_taskprocessor_listener_get_tps(listener); if (ast_threadpool_push(ser->pool, execute_tasks, tps)) { ast_taskprocessor_unreference(tps); } } }
static int execute_tasks(void *data) { struct ast_taskprocessor *tps = data; ast_threadstorage_set_ptr(¤t_serializer, tps); while (ast_taskprocessor_execute(tps)) { /* No-op */ } ast_threadstorage_set_ptr(¤t_serializer, NULL); ast_taskprocessor_unreference(tps); return 0; }
static void subscription_dtor(void *obj) { struct stasis_subscription *sub = obj; /* Subscriptions need to be manually unsubscribed before destruction * b/c there's a cyclic reference between topics and subscriptions */ ast_assert(!stasis_subscription_is_subscribed(sub)); /* If there are any messages in flight to this subscription; that would * be bad. */ ast_assert(stasis_subscription_is_done(sub)); ao2_cleanup(sub->topic); sub->topic = NULL; ast_taskprocessor_unreference(sub->mailbox); sub->mailbox = NULL; ast_cond_destroy(&sub->join_cond); }
static void serializer_destroy(void *obj) { struct serializer *ser = obj; ast_taskprocessor_unreference(ser->serializer); }
static pj_bool_t distributor(pjsip_rx_data *rdata) { pjsip_dialog *dlg; struct distributor_dialog_data *dist = NULL; struct ast_taskprocessor *serializer = NULL; pjsip_rx_data *clone; if (!ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) { /* * Ignore everything until we are fully booted. Let the * peer retransmit messages until we are ready. */ return PJ_TRUE; } dlg = find_dialog(rdata); if (dlg) { ast_debug(3, "Searching for serializer associated with dialog %s for %s\n", dlg->obj_name, pjsip_rx_data_get_info(rdata)); dist = ao2_find(dialog_associations, dlg, OBJ_SEARCH_KEY); if (dist) { ao2_lock(dist); serializer = ao2_bump(dist->serializer); ao2_unlock(dist); if (serializer) { ast_debug(3, "Found serializer %s associated with dialog %s\n", ast_taskprocessor_name(serializer), dlg->obj_name); } } } if (serializer) { /* We have a serializer so we know where to send the message. */ } else if (rdata->msg_info.msg->type == PJSIP_RESPONSE_MSG) { ast_debug(3, "No dialog serializer for %s. Using request transaction as basis.\n", pjsip_rx_data_get_info(rdata)); serializer = find_request_serializer(rdata); if (!serializer) { /* * Pick a serializer for the unmatched response. * We couldn't determine what serializer originally * sent the request or the serializer is gone. */ serializer = ast_sip_get_distributor_serializer(rdata); } } else if (!pjsip_method_cmp(&rdata->msg_info.msg->line.req.method, &pjsip_cancel_method) || !pjsip_method_cmp(&rdata->msg_info.msg->line.req.method, &pjsip_bye_method)) { /* We have a BYE or CANCEL request without a serializer. */ pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, PJSIP_SC_CALL_TSX_DOES_NOT_EXIST, NULL, NULL, NULL); ao2_cleanup(dist); return PJ_TRUE; } else { if (ast_taskprocessor_alert_get()) { /* * When taskprocessors get backed up, there is a good chance that * we are being overloaded and need to defer adding new work to * the system. To defer the work we will ignore the request and * rely on the peer's transport layer to retransmit the message. * We usually work off the overload within a few seconds. The * alternative is to send back a 503 response to these requests * and be done with it. */ ast_debug(3, "Taskprocessor overload alert: Ignoring '%s'.\n", pjsip_rx_data_get_info(rdata)); ao2_cleanup(dist); return PJ_TRUE; } /* Pick a serializer for the out-of-dialog request. */ serializer = ast_sip_get_distributor_serializer(rdata); } if (pjsip_rx_data_clone(rdata, 0, &clone) != PJ_SUCCESS) { ast_taskprocessor_unreference(serializer); ao2_cleanup(dist); return PJ_TRUE; } if (dist) { ao2_lock(dist); clone->endpt_info.mod_data[endpoint_mod.id] = ao2_bump(dist->endpoint); ao2_unlock(dist); ao2_cleanup(dist); } if (ast_sip_push_task(serializer, distribute, clone)) { ao2_cleanup(clone->endpt_info.mod_data[endpoint_mod.id]); pjsip_rx_data_free_cloned(clone); } ast_taskprocessor_unreference(serializer); return PJ_TRUE; }
static void *tps_shutdown_thread(void *data) { struct ast_taskprocessor *tps = data; ast_taskprocessor_unreference(tps); return NULL; }