int metadata_running = 0;
-// always lock this when trying to make a conn the principal conn,
-// e.g. during an ANNOUNCE (Classic AirPlay) or SETUP (AirPlay 2)
-pthread_mutex_t principal_conn_acquisition_lock = PTHREAD_MUTEX_INITIALIZER;
// always lock this when accessing the principal conn value
-pthread_mutex_t principal_conn_lock = PTHREAD_MUTEX_INITIALIZER;
+// use a read lock when consulting and holding it
+// use a write lock if you want to change it
+pthread_rwlock_t principal_conn_lock = PTHREAD_RWLOCK_INITIALIZER;
// always lock this when accessing the list of connection threads
pthread_mutex_t conns_lock = PTHREAD_MUTEX_INITIALIZER;
// other devices.
void release_play_lock(rtsp_conn_info *conn) {
- pthread_cleanup_debug_mutex_lock(&principal_conn_lock, 100000,
- 1); // don't let the principal_conn be changed
+ // no need thread cancellation points in here
+ pthread_rwlock_wrlock(&principal_conn_lock);
if (principal_conn == conn) { // if we have the player
if (conn != NULL)
debug(2, "Connection %d: principal_conn released.", conn->connection_number);
principal_conn = NULL; // let it go
}
- pthread_cleanup_pop(1); // release the principal_conn lock
+ pthread_rwlock_unlock(&principal_conn_lock);
}
// stop the current principal_conn from playing if necessary and make conn the principal_conn.
int get_play_lock(rtsp_conn_info *conn, int allow_session_interruption) {
int response = 0;
- pthread_cleanup_debug_mutex_lock(&principal_conn_lock, 100000, 1);
+ pthread_rwlock_wrlock(&principal_conn_lock);
+ pthread_cleanup_push(rwlock_unlock,(void *)&principal_conn_lock);
if (principal_conn != NULL)
- debug(2, "Connection %d: is requested to relinquish principal_conn.",
+ debug(1, "Connection %d: is requested to relinquish principal_conn.",
principal_conn->connection_number);
if (conn != NULL)
debug(2, "Connection %d: request to acquire principal_conn.", conn->connection_number);
warn("Connection %d: request to re-acquire principal_conn!",
principal_conn->connection_number);
} else if (allow_session_interruption != 0) {
- player_stop(principal_conn);
- debug(2, "Connection %d: termination requested.", principal_conn->connection_number);
- pthread_cancel(principal_conn->thread);
- usleep(2000000); // don't know why this delay is needed.
+ rtsp_conn_info *previous_principal_conn = principal_conn;
+ principal_conn = NULL; // no longer the principal conn
+ pthread_cancel(previous_principal_conn->thread);
+ // usleep(1000000); // don't know why this delay is needed.
principal_conn = conn; // make the conn the new principal_conn
response = 1; // interrupted an existing session
} else {
}
rtsp_message *msg_init(void) {
+ // no thread cancellation points here
+ int rc = pthread_mutex_lock(&reference_counter_lock);
+ if (rc)
+ debug(1, "Error %d locking reference counter lock");
+
rtsp_message *msg = malloc(sizeof(rtsp_message));
if (msg) {
memset(msg, 0, sizeof(rtsp_message));
die("msg_init -- can not allocate memory for rtsp_message %d.", msg_indexes);
}
// debug(1,"msg_init -- create item %d.", msg->index_number);
+
+ rc = pthread_mutex_unlock(&reference_counter_lock);
+ if (rc)
+ debug(1, "Error %d unlocking reference counter lock");
+
return msg;
}
} else {
void *qualifier_response_data = NULL;
size_t qualifier_response_data_length = 0;
+
+
+ pthread_rwlock_rdlock(&principal_conn_lock); // don't let the principal_conn be changed
+ pthread_cleanup_push(rwlock_unlock,(void *)&principal_conn_lock);
+
+
+
+
if (add_pstring_to_malloc("acl=0", &qualifier_response_data,
&qualifier_response_data_length) == 0)
debug(1, "Problem");
free(vs);
// pkString_make(pkString, sizeof(pkString), config.airplay_device_id);
// plist_dict_set_item(response_plist, "pk", plist_new_string(pkString));
+ pthread_cleanup_pop(1); // release the principal_conn lock
plist_to_bin(response_plist, &resp->content, &resp->contentlength);
if (resp->contentlength == 0)
debug(1, "GET /info Stage 1: response bplist not created!");
#endif
}
conn->groupContainsGroupLeader = 0;
- config.airplay_statusflags &= (0xffffffff - (1 << 11)); // DeviceSupportsRelay
- build_bonjour_strings(NULL);
- debug(2, "Connection %d: TEARDOWN mdns_update on %s.", conn->connection_number,
- get_category_string(conn->airplay_stream_category));
- mdns_update(NULL, secondary_txt_records);
if (conn->dacp_active_remote != NULL) {
free(conn->dacp_active_remote);
conn->dacp_active_remote = NULL;
void handle_teardown_2(rtsp_conn_info *conn, __attribute__((unused)) rtsp_message *req,
rtsp_message *resp) {
- debug(2, "Connection %d: TEARDOWN %s.", conn->connection_number,
+ debug(1, "Connection %d: TEARDOWN %s.", conn->connection_number,
get_category_string(conn->airplay_stream_category));
debug_log_rtsp_message(2, "TEARDOWN: ", req);
- // if (have_player(conn)) {
resp->respcode = 200;
msg_add_header(resp, "Connection", "close");
-
plist_t messagePlist = plist_from_rtsp_content(req);
if (messagePlist != NULL) {
// now see if the incoming plist contains a "streams" array
get_category_string(conn->airplay_stream_category));
teardown_phase_one(conn); // try to do phase one anyway
teardown_phase_two(conn);
+
+ // only update these things if you're (still) the principal conn
+ pthread_rwlock_rdlock(&principal_conn_lock); // don't let the principal_conn be changed
+ pthread_cleanup_push(rwlock_unlock,(void *)&principal_conn_lock);
+ if ((principal_conn == conn) && (conn->airplay_stream_category == ptp_stream)) {
+ config.airplay_statusflags &= (0xffffffff - (1 << 11)); // DeviceSupportsRelay
+ build_bonjour_strings(conn);
+ debug(2, "Connection %d: TEARDOWN mdns_update on %s.", conn->connection_number,
+ get_category_string(conn->airplay_stream_category));
+ mdns_update(NULL, secondary_txt_records);
+ }
+ pthread_cleanup_pop(1); // release the principal_conn lock
debug(2, "Connection %d: TEARDOWN %s -- close the connection complete",
conn->connection_number, get_category_string(conn->airplay_stream_category));
release_play_lock(conn);
debug(1, "Connection %d: missing plist!", conn->connection_number);
resp->respcode = 451; // don't know what to do here
}
+
// debug(1,"Bogus exit for valgrind -- remember to comment it out!.");
// exit(EXIT_SUCCESS); //
}
conn->connection_number); // kill all the other
listeners
*/
+ // only update these things if you're (still) the principal conn
+ pthread_rwlock_wrlock(&principal_conn_lock); // don't let the principal_conn be changed
+ pthread_cleanup_push(rwlock_unlock,(void *)&principal_conn_lock);
+ if (principal_conn == conn) {
+ config.airplay_statusflags |= 1 << 11; // DeviceSupportsRelay
+ build_bonjour_strings(conn);
+ debug(2, "Connection %d: SETUP mdns_update on %s.", conn->connection_number,
+ get_category_string(conn->airplay_stream_category));
+ mdns_update(NULL, secondary_txt_records);
+ }
+ pthread_cleanup_pop(1); // release the principal_conn lock
- config.airplay_statusflags |= 1 << 11; // DeviceSupportsRelay
- build_bonjour_strings(conn);
- debug(2, "Connection %d: SETUP mdns_update on %s.", conn->connection_number,
- get_category_string(conn->airplay_stream_category));
- mdns_update(NULL, secondary_txt_records);
resp->respcode = 200;
} else {
debug(1, "SETUP on Connection %d: PTP setup -- no timingPeerInfo plist.",
shairport_sync_set_volume(shairportSyncSkeleton, volume);
} else {
#endif
- pthread_cleanup_debug_mutex_lock(&principal_conn_lock, 100000,
- 1); // don't let the principal_conn be changed
+ pthread_rwlock_rdlock(&principal_conn_lock); // don't let the principal_conn be changed
+ pthread_cleanup_push(rwlock_unlock,(void *)&principal_conn_lock);
if (principal_conn == conn) {
player_volume(volume, conn);
}