Commit 98d932d1 authored by Pekka Pessi's avatar Pekka Pessi

nta: fix sf.net bug #1810115, crash after nta_destroy()

su_msg_t delivery, again.

Thanks to Mikhail Zabaluev for reporting this.

darcs-hash:20071011152559-88462-bffecc768bdd0e56167fc4bccaeb52e7d096460d.gz
parent 64c8de2f
......@@ -256,12 +256,6 @@ static int outgoing_recv_reliable(nta_outgoing_t *orq, msg_t *msg, sip_t *sip);
/* Internal message passing */
union sm_arg_u {
struct leg_recv_s {
nta_leg_t *leg;
msg_t *msg;
tport_t *tport;
} a_leg_recv[1];
struct outgoing_recv_s {
nta_outgoing_t *orq;
msg_t *msg;
......@@ -6649,8 +6643,7 @@ nta_outgoing_t *nta_outgoing_tcancel(nta_outgoing_t *orq,
#if HAVE_SOFIA_SRESOLV
if (!orq->orq_resolved) {
if (orq->orq_resolver)
outgoing_cancel_resolver(orq);
outgoing_destroy_resolver(orq);
outgoing_reply(orq, SIP_487_REQUEST_CANCELLED, 1);
return NULL; /* XXX - Does anyone care about reply? */
}
......@@ -7740,6 +7733,9 @@ void outgoing_cut_off(nta_outgoing_t *orq)
su_inline
void outgoing_reclaim(nta_outgoing_t *orq)
{
if (orq->orq_status2b)
*orq->orq_status2b = -1;
if (orq->orq_request)
msg_destroy(orq->orq_request), orq->orq_request = NULL;
if (orq->orq_response)
......@@ -8724,6 +8720,8 @@ int outgoing_reply(nta_outgoing_t *orq, int status, char const *phrase,
a->sip = sip;
a->status = status;
orq->orq_status2b = &a->status;
if (su_msg_send(su_msg) == SU_SUCCESS) {
return 0;
}
......@@ -8742,8 +8740,14 @@ void outgoing_delayed_recv(su_root_magic_t *rm,
union sm_arg_u *u)
{
struct outgoing_recv_s *a = u->a_outgoing_recv;
if (outgoing_recv(a->orq, a->status, a->msg, a->sip) < 0 && a->msg)
msg_destroy(a->msg);
if (a->status > 0) {
a->orq->orq_status2b = 0;
if (outgoing_recv(a->orq, a->status, a->msg, a->sip) >= 0)
return;
}
msg_destroy(a->msg);
}
......
......@@ -544,6 +544,8 @@ struct nta_outgoing_s
char const *orq_branch; /**< Transaction branch */
char const *orq_via_branch; /**< @Via branch */
int *orq_status2b; /**< Delayed response */
nta_outgoing_t *orq_cancel; /**< CANCEL transaction */
uint32_t orq_rseq; /**< Latest incoming rseq */
......
......@@ -445,6 +445,54 @@ int api_test_deinit(agent_t *ag)
END();
}
static int api_test_destroy(agent_t *ag)
{
nta_agent_t *nta;
su_root_t *root;
su_home_t home[1];
nta_outgoing_t *orq;
nta_leg_t *leg;
int i;
BEGIN();
memset(home, 0, sizeof home);
home->suh_size = sizeof home;
su_home_init(home);
TEST_1(root = su_root_create(NULL));
for (i = 0; i < 2; i++) {
TEST_1(nta = nta_agent_create(root,
(url_string_t *)"sip:*:*",
NULL,
NULL,
TAG_END()));
TEST_1(leg = nta_leg_tcreate(nta, NULL, NULL,
NTATAG_NO_DIALOG(1),
TAG_END()));
/* This creates a delayed response message */
orq = nta_outgoing_tcreate(leg, outgoing_callback, ag, NULL,
SIP_METHOD_MESSAGE,
URL_STRING_MAKE("sip:foo.bar;transport=none"),
SIPTAG_FROM_STR("<sip:bar.foo>"),
SIPTAG_TO_STR("<sip:foo.bar>"),
TAG_END());
TEST_1(orq);
TEST_VOID(nta_outgoing_destroy(orq));
TEST_VOID(nta_leg_destroy(leg));
TEST_VOID(nta_agent_destroy(nta));
}
TEST_VOID(su_root_destroy(root));
TEST_VOID(su_home_deinit(home));
END();
}
/* Get and check parameters */
int api_test_params(agent_t *ag)
{
......@@ -1114,22 +1162,9 @@ static int api_test_errors(agent_t *ag)
TEST_P(nta_outgoing_tcancel(NONE, NULL, NULL, TAG_END()), NULL);
TEST_VOID(nta_outgoing_destroy(NONE));
#if 0
nta_reliable_t *nta_reliable_treply(nta_incoming_t *ireq,
nta_prack_f *callback,
nta_reliable_magic_t *rmagic,
int status, char const *phrase,
tag_type_t tag,
tag_value_t value, ...);
nta_reliable_t *nta_reliable_mreply(nta_incoming_t *irq,
nta_prack_f *callback,
nta_reliable_magic_t *rmagic,
msg_t *msg);
void nta_reliable_destroy(nta_reliable_t *);
#endif
TEST_P(nta_reliable_treply(NULL, NULL, NULL, 0, NULL, TAG_END()), NULL);
TEST_P(nta_reliable_mreply(NULL, NULL, NULL, NULL), NULL);
TEST_VOID(nta_reliable_destroy(NULL));
TEST_VOID(nta_agent_destroy(nta));
TEST_VOID(su_root_destroy(root));
......@@ -1382,6 +1417,7 @@ int main(int argc, char *argv[])
retval |= api_test_init(ag); fflush(stdout); SINGLE_FAILURE_CHECK();
if (retval == 0) {
retval |= api_test_errors(ag); SINGLE_FAILURE_CHECK();
retval |= api_test_destroy(ag); SINGLE_FAILURE_CHECK();
retval |= api_test_params(ag); SINGLE_FAILURE_CHECK();
retval |= api_test_stats(ag); SINGLE_FAILURE_CHECK();
retval |= api_test_dialog_matching(ag); SINGLE_FAILURE_CHECK();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment