Skinny: solve deadlocks and more

- Solve deadlock:
  + associate all skinny_profile_find_session with the corresponding
    switch_core_session_rwunlock
  + lock the newly created session in skinny_create_ingoing_session
  + enhance rwlocks debugging
- Shared lines:
  + Inform shared lines on answering
  + Answering line has info after other shared lines
This commit is contained in:
Mathieu Parent 2010-04-08 22:38:24 +02:00
parent 3b83541f79
commit 58595bdaec
3 changed files with 54 additions and 23 deletions

View File

@ -235,14 +235,22 @@ char * skinny_profile_find_session_uuid(skinny_profile_t *profile, listener_t *l
return helper.channel_uuid; return helper.channel_uuid;
} }
#ifdef SWITCH_DEBUG_RWLOCKS
switch_core_session_t * skinny_profile_perform_find_session(skinny_profile_t *profile, listener_t *listener, uint32_t *line_instance_p, uint32_t call_id, const char *file, const char *func, int line)
#else
switch_core_session_t * skinny_profile_find_session(skinny_profile_t *profile, listener_t *listener, uint32_t *line_instance_p, uint32_t call_id) switch_core_session_t * skinny_profile_find_session(skinny_profile_t *profile, listener_t *listener, uint32_t *line_instance_p, uint32_t call_id)
#endif
{ {
char *uuid; char *uuid;
switch_core_session_t *result = NULL; switch_core_session_t *result = NULL;
uuid = skinny_profile_find_session_uuid(profile, listener, line_instance_p, call_id); uuid = skinny_profile_find_session_uuid(profile, listener, line_instance_p, call_id);
if(!zstr(uuid)) { if(!zstr(uuid)) {
#ifdef SWITCH_DEBUG_RWLOCKS
result = switch_core_session_perform_locate(uuid, file, func, line);
#else
result = switch_core_session_locate(uuid); result = switch_core_session_locate(uuid);
#endif
if(!result) { if(!result) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
"Unable to find session %s on %s:%d, line %d\n", "Unable to find session %s on %s:%d, line %d\n",
@ -650,7 +658,6 @@ int channel_on_hangup_callback(void *pArg, int argc, char **argv, char **columnN
/* TODO: DefineTimeDate */ /* TODO: DefineTimeDate */
send_set_speaker_mode(listener, SKINNY_SPEAKER_OFF); send_set_speaker_mode(listener, SKINNY_SPEAKER_OFF);
send_set_ringer(listener, SKINNY_RING_OFF, SKINNY_RING_FOREVER, 0, call_id); send_set_ringer(listener, SKINNY_RING_OFF, SKINNY_RING_FOREVER, 0, call_id);
} }
return 0; return 0;
} }

View File

@ -189,7 +189,12 @@ switch_status_t skinny_profile_dump(const skinny_profile_t *profile, switch_stre
switch_status_t skinny_profile_find_listener_by_device_name(skinny_profile_t *profile, const char *device_name, listener_t **listener); switch_status_t skinny_profile_find_listener_by_device_name(skinny_profile_t *profile, const char *device_name, listener_t **listener);
switch_status_t skinny_profile_find_listener_by_device_name_and_instance(skinny_profile_t *profile, const char *device_name, uint32_t device_instance, listener_t **listener); switch_status_t skinny_profile_find_listener_by_device_name_and_instance(skinny_profile_t *profile, const char *device_name, uint32_t device_instance, listener_t **listener);
char * skinny_profile_find_session_uuid(skinny_profile_t *profile, listener_t *listener, uint32_t *line_instance_p, uint32_t call_id); char * skinny_profile_find_session_uuid(skinny_profile_t *profile, listener_t *listener, uint32_t *line_instance_p, uint32_t call_id);
#ifdef SWITCH_DEBUG_RWLOCKS
switch_core_session_t * skinny_profile_perform_find_session(skinny_profile_t *profile, listener_t *listener, uint32_t *line_instance_p, uint32_t call_id, const char *file, const char *func, int line);
#define skinny_profile_find_session(profile, listener, line_instance_p, call_id) skinny_profile_perform_find_session(profile, listener, line_instance_p, call_id, __FILE__, __SWITCH_FUNC__, __LINE__)
#else
switch_core_session_t * skinny_profile_find_session(skinny_profile_t *profile, listener_t *listener, uint32_t *line_instance_p, uint32_t call_id); switch_core_session_t * skinny_profile_find_session(skinny_profile_t *profile, listener_t *listener, uint32_t *line_instance_p, uint32_t call_id);
#endif
switch_status_t dump_device(skinny_profile_t *profile, const char *device_name, switch_stream_handle_t *stream); switch_status_t dump_device(skinny_profile_t *profile, const char *device_name, switch_stream_handle_t *stream);
/*****************************************************************************/ /*****************************************************************************/

View File

@ -446,13 +446,13 @@ switch_status_t skinny_create_ingoing_session(listener_t *listener, uint32_t *li
line_instance = *line_instance_p; line_instance = *line_instance_p;
if((nsession = skinny_profile_find_session(listener->profile, listener, line_instance_p, 0))) { if((nsession = skinny_profile_find_session(listener->profile, listener, line_instance_p, 0))) {
switch_core_session_rwunlock(nsession);
if(skinny_line_get_state(listener, *line_instance_p, 0) == SKINNY_OFF_HOOK) { if(skinny_line_get_state(listener, *line_instance_p, 0) == SKINNY_OFF_HOOK) {
/* Reuse existing session */ /* Reuse existing session */
*session = nsession; *session = nsession;
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
skinny_session_hold_line(nsession, listener, *line_instance_p); skinny_session_hold_line(nsession, listener, *line_instance_p);
switch_core_session_rwunlock(nsession);
} }
*line_instance_p = line_instance; *line_instance_p = line_instance;
if(*line_instance_p == 0) { if(*line_instance_p == 0) {
@ -494,7 +494,11 @@ switch_status_t skinny_create_ingoing_session(listener_t *listener, uint32_t *li
"Error Creating Session thread\n"); "Error Creating Session thread\n");
goto error; goto error;
} }
if (switch_core_session_read_lock(nsession) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(nsession), SWITCH_LOG_CRIT,
"Error Locking Session\n");
goto error;
}
if (!(tech_pvt->caller_profile = switch_caller_profile_new(switch_core_session_get_pool(nsession), if (!(tech_pvt->caller_profile = switch_caller_profile_new(switch_core_session_get_pool(nsession),
NULL, listener->profile->dialplan, NULL, listener->profile->dialplan,
button->shortname, button->name, button->shortname, button->name,
@ -579,8 +583,6 @@ switch_status_t skinny_session_process_dest(switch_core_session_t *session, list
skinny_session_start_media(session, listener, line_instance); skinny_session_start_media(session, listener, line_instance);
} }
switch_core_session_rwunlock(session);
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
@ -603,8 +605,6 @@ switch_status_t skinny_session_ring_out(switch_core_session_t *session, listener
line_instance, tech_pvt->call_id); line_instance, tech_pvt->call_id);
skinny_send_call_info(session, listener, line_instance); skinny_send_call_info(session, listener, line_instance);
switch_core_session_rwunlock(session);
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
@ -643,16 +643,14 @@ int skinny_session_answer_callback(void *pArg, int argc, char **argv, char **col
if(!strcmp(device_name, helper->listener->device_name) if(!strcmp(device_name, helper->listener->device_name)
&& (device_instance == helper->listener->device_instance) && (device_instance == helper->listener->device_instance)
&& (line_instance == helper->line_instance)) {/* the answering line */ && (line_instance == helper->line_instance)) {/* the answering line */
/* nothing */
} else {
send_set_ringer(listener, SKINNY_RING_OFF, SKINNY_RING_FOREVER, 0, helper->tech_pvt->call_id); send_define_current_time_date(listener);
send_set_speaker_mode(listener, SKINNY_SPEAKER_ON);
send_set_lamp(listener, SKINNY_BUTTON_LINE, line_instance, SKINNY_LAMP_ON); send_set_lamp(listener, SKINNY_BUTTON_LINE, line_instance, SKINNY_LAMP_ON);
skinny_line_set_state(listener, line_instance, helper->tech_pvt->call_id, SKINNY_OFF_HOOK); skinny_line_set_state(listener, line_instance, helper->tech_pvt->call_id, SKINNY_IN_USE_REMOTELY);
/* send_select_soft_keys(listener, line_instance, helper->tech_pvt->call_id, SKINNY_KEY_SET_OFF_HOOK, 0xffff); */ send_select_soft_keys(listener, line_instance, helper->tech_pvt->call_id, 10, 0x0002);
/* display_prompt_status(listener, 0, "\200\000", send_display_prompt_status(listener, 0, "\200\037", line_instance, helper->tech_pvt->call_id);
line_instance, tech_pvt->call_id); */ send_set_ringer(listener, SKINNY_RING_OFF, SKINNY_RING_FOREVER, 0, helper->tech_pvt->call_id);
send_activate_call_plane(listener, line_instance);
} }
} }
return 0; return 0;
@ -671,6 +669,12 @@ switch_status_t skinny_session_answer(switch_core_session_t *session, listener_t
channel = switch_core_session_get_channel(session); channel = switch_core_session_get_channel(session);
tech_pvt = switch_core_session_get_private(session); tech_pvt = switch_core_session_get_private(session);
send_set_ringer(listener, SKINNY_RING_OFF, SKINNY_RING_FOREVER, 0, tech_pvt->call_id);
send_set_speaker_mode(listener, SKINNY_SPEAKER_ON);
send_set_lamp(listener, SKINNY_BUTTON_LINE, line_instance, SKINNY_LAMP_ON);
skinny_line_set_state(listener, line_instance, tech_pvt->call_id, SKINNY_OFF_HOOK);
send_activate_call_plane(listener, line_instance);
helper.tech_pvt = tech_pvt; helper.tech_pvt = tech_pvt;
helper.listener = listener; helper.listener = listener;
helper.line_instance = line_instance; helper.line_instance = line_instance;
@ -679,8 +683,6 @@ switch_status_t skinny_session_answer(switch_core_session_t *session, listener_t
skinny_session_start_media(session, listener, line_instance); skinny_session_start_media(session, listener, line_instance);
switch_core_session_rwunlock(session);
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
@ -717,8 +719,6 @@ switch_status_t skinny_session_start_media(switch_core_session_t *session, liste
tech_pvt->call_id); tech_pvt->call_id);
skinny_send_call_info(session, listener, line_instance); skinny_send_call_info(session, listener, line_instance);
switch_core_session_rwunlock(session);
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
@ -739,8 +739,6 @@ switch_status_t skinny_session_hold_line(switch_core_session_t *session, listene
switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING); switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING);
switch_core_session_rwunlock(session);
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
@ -2002,6 +2000,11 @@ switch_status_t skinny_handle_off_hook_message(listener_t *listener, skinny_mess
skinny_session_process_dest(session, listener, line_instance, NULL, '\0', 0); skinny_session_process_dest(session, listener, line_instance, NULL, '\0', 0);
} }
if(session) {
switch_core_session_rwunlock(session);
}
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
@ -2037,6 +2040,11 @@ switch_status_t skinny_handle_stimulus_message(listener_t *listener, skinny_mess
default: default:
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unknown Stimulus Type Received [%d]\n", request->data.stimulus.instance_type); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unknown Stimulus Type Received [%d]\n", request->data.stimulus.instance_type);
} }
if(session) {
switch_core_session_rwunlock(session);
}
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
@ -2118,9 +2126,13 @@ switch_status_t skinny_handle_open_receive_channel_ack_message(listener_t *liste
} }
switch_channel_mark_answered(channel); switch_channel_mark_answered(channel);
switch_core_session_rwunlock(session);
} }
end: end:
if(session) {
switch_core_session_rwunlock(session);
}
return status; return status;
} }
@ -2174,6 +2186,10 @@ switch_status_t skinny_handle_keypad_button_message(listener_t *listener, skinny
switch_core_session_rwunlock(session); switch_core_session_rwunlock(session);
} }
if(session) {
switch_core_session_rwunlock(session);
}
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
@ -2195,9 +2211,12 @@ switch_status_t skinny_handle_on_hook_message(listener_t *listener, skinny_messa
channel = switch_core_session_get_channel(session); channel = switch_core_session_get_channel(session);
switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING); switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING);
}
if(session) {
switch_core_session_rwunlock(session); switch_core_session_rwunlock(session);
} }
return status; return status;
} }