Index: channels/chan_sip.c =================================================================== --- channels/chan_sip.c (revision 126681) +++ channels/chan_sip.c (working copy) @@ -10176,8 +10176,10 @@ { struct sip_peer *peer = (struct sip_peer *)data; + /* We are the schedule, so we're allowed to do this */ peer->pokeexpire = -1; sip_poke_peer(peer, 0); + unref_peer(peer, "sip_poke_peer_s ended"); return 0; } @@ -10229,7 +10231,10 @@ peer->addr.sin_port = htons(port); if (sipsock < 0) { /* SIP isn't up yet, so schedule a poke only, pretty soon */ - AST_SCHED_REPLACE(peer->pokeexpire, sched, ast_random() % 5000 + 1, sip_poke_peer_s, peer); + AST_SCHED_REPLACE_UNREF(peer->pokeexpire, sched, ast_random() % 5000 + 1, sip_poke_peer_s, peer, + unref_peer(peer, "removing peer poke at startup (should this ever happen?)"), + ast_log(LOG_WARNING, "Unable to schedule peer poke at startup\n"), + ref_peer(peer, "Peer poke startup")); } else { sip_poke_peer(peer, 0); } @@ -16428,9 +16433,12 @@ p->needdestroy = 1; /* Try again eventually */ - AST_SCHED_REPLACE(peer->pokeexpire, sched, + AST_SCHED_REPLACE_UNREF(peer->pokeexpire, sched, is_reachable ? peer->qualifyfreq : DEFAULT_FREQ_NOTOK, - sip_poke_peer_s, peer); + sip_poke_peer_s, peer, + unref_peer(peer, "Cancelling old peer poke"), + ast_log(LOG_WARNING, "Unable to schedule new peer poke\n"), + ref_peer(peer, "Scheduling new peer poke")); /* unref_peer(peer, "unref relatedpeer ptr var at end of handle_response_peerpoke"); */ } @@ -20254,7 +20262,10 @@ } -/*! \brief React to lack of answer to Qualify poke */ +/*! \brief React to lack of answer to Qualify poke + * If this routine is not called as part of a schedule, then the peer refcount + * should be incremented first. + */ static int sip_poke_noanswer(const void *data) { struct sip_peer *peer = (struct sip_peer *)data; @@ -20274,9 +20285,12 @@ peer->lastms = -1; ast_device_state_changed("SIP/%s", peer->name); - /* Try again quickly */ - AST_SCHED_REPLACE(peer->pokeexpire, sched, - DEFAULT_FREQ_NOTOK, sip_poke_peer_s, peer); + /* Try again quickly - we are the schedule, so we can't cancel ourselves through the scheduler interface */ + if (!(peer->pokeexpire = ast_sched_add(sched, DEFAULT_FREQ_NOTOK, sip_poke_peer_s, peer))) { + ast_log(LOG_WARNING, "Unable to reschedule peer poke\n"); + unref_peer(peer, "Rescheduling peer poke failed"); + } + return 0; } @@ -20291,7 +20305,7 @@ if ((!peer->maxms && !force) || !peer->addr.sin_addr.s_addr) { /* IF we have no IP, or this isn't to be monitored, return immediately after clearing things out */ - AST_SCHED_DEL(sched, peer->pokeexpire); + AST_SCHED_DEL_UNREF(sched, peer->pokeexpire, unref_peer(peer, "cancelling pokeexpire in sip_poke_peer, as we have no IP")); peer->lastms = 0; if (peer->call) @@ -20331,7 +20345,7 @@ build_callid_pvt(p); ao2_t_link(dialogs, p, "Linking in under new name"); - AST_SCHED_DEL(sched, peer->pokeexpire); + AST_SCHED_DEL_UNREF(sched, peer->pokeexpire, unref_peer(peer, "Deleting peer poke (to be rescheduled)")); if (p->relatedpeer) p->relatedpeer = unref_peer(p->relatedpeer,"unsetting the relatedpeer field in the dialog, before it is set to something else."); @@ -20345,10 +20359,15 @@ #endif peer->ps = ast_tvnow(); if (xmitres == XMIT_ERROR) { + ref_peer(peer, "xmit_error, sending to sip_poke_noanswer (needs to inherit a reference)"); sip_poke_noanswer(peer); /* Immediately unreachable, network problems */ } else if (!force) { - AST_SCHED_REPLACE(peer->pokeexpire, sched, - peer->maxms * 2, sip_poke_noanswer, peer); + /* pokeexpire should already be -1, unless something really bad happened */ + AST_SCHED_REPLACE_UNREF(peer->pokeexpire, sched, + peer->maxms * 2, sip_poke_noanswer, peer, + unref_peer(peer, "should not ever happen"), + ast_log(LOG_WARNING, "Unable to reschedule peer poke"), + ref_peer(peer, "Scheduling peer poke")); } dialog_unref(p, "unref dialog at end of sip_poke_peer, obtained from sip_alloc, just before it goes out of scope"); return 0; @@ -22814,7 +22833,10 @@ while ((peer = ao2_t_iterator_next(&i, "iterate thru peers table"))) { ao2_lock(peer); ms += 100; - AST_SCHED_REPLACE(peer->pokeexpire, sched, ms, sip_poke_peer_s, peer); + AST_SCHED_REPLACE_UNREF(peer->pokeexpire, sched, ms, sip_poke_peer_s, peer, + unref_peer(peer, "Deleted old sched in sip_poke_all_peers"), + ast_log(LOG_ERROR, "Unable to reschedule peer poke!\n"), + ref_peer(peer, "Schedule poke in sip_poke_all_peers")); ao2_unlock(peer); unref_peer(peer, "toss iterator peer ptr"); }