DNS: Need to use the same serializer for a pjproject SIP transaction.

All send/receive processing for a SIP transaction needs to be done under
the same threadpool serializer to prevent reentrancy problems inside
pjproject when using an external DNS resolver to process messages for the
transaction.

* Add threadpool API call to get the current serializer associated with
the worker thread.

* Pick a serializer from a pool of default serializers if the caller of
res_pjsip.c:ast_sip_push_task() does not provide one.

This is a simple way to ensure that all outgoing SIP request messages are
processed under a serializer.  Otherwise, any place where a pushed task is
done that would result in an outgoing out-of-dialog request would need to
be modified to supply a serializer.  Serializers from the default
serializer pool are picked in a round robin sequence for simplicity.

A side effect is that the default serializer pool will limit the growth of
the thread pool from random tasks.  This is not necessarily a bad thing.

* Made pjsip_resolver.c use the requesting thread's serializer to execute
the async callback.

* Made pjsip_distributor.c save the thread's serializer name on the
outgoing request tdata struct so the response can be processed under the
same serializer.

ASTERISK-25115 #close
Reported by: John Bigelow

Change-Id: Iea71c16ce1132017b5791635e198b8c27973f40a
This commit is contained in:
Richard Mudgett
2015-06-05 15:37:33 -05:00
parent b23f33e7e5
commit 30cd559345
5 changed files with 211 additions and 20 deletions

View File

@@ -1150,13 +1150,17 @@ static struct serializer *serializer_create(struct ast_threadpool *pool)
return ser;
}
AST_THREADSTORAGE_RAW(current_serializer);
static int execute_tasks(void *data)
{
struct ast_taskprocessor *tps = data;
ast_threadstorage_set_ptr(&current_serializer, tps);
while (ast_taskprocessor_execute(tps)) {
/* No-op */
}
ast_threadstorage_set_ptr(&current_serializer, NULL);
ast_taskprocessor_unreference(tps);
return 0;
@@ -1192,6 +1196,11 @@ static struct ast_taskprocessor_listener_callbacks serializer_tps_listener_callb
.shutdown = serializer_shutdown,
};
struct ast_taskprocessor *ast_threadpool_serializer_get_current(void)
{
return ast_threadstorage_get_ptr(&current_serializer);
}
struct ast_taskprocessor *ast_threadpool_serializer(const char *name, struct ast_threadpool *pool)
{
RAII_VAR(struct serializer *, ser, NULL, ao2_cleanup);