Cleaned up, fixed and robustified semaphore and signal related code

This commit is contained in:
Thulinma 2018-11-01 16:11:47 +01:00
parent ee9b076b76
commit 24006648f9
7 changed files with 165 additions and 131 deletions

View file

@ -401,7 +401,7 @@ void Util::Config::activate() {
struct sigaction cur_action; struct sigaction cur_action;
new_action.sa_sigaction = signal_handler; new_action.sa_sigaction = signal_handler;
sigemptyset(&new_action.sa_mask); sigemptyset(&new_action.sa_mask);
new_action.sa_flags = 0; new_action.sa_flags = SA_SIGINFO;
sigaction(SIGINT, &new_action, NULL); sigaction(SIGINT, &new_action, NULL);
sigaction(SIGHUP, &new_action, NULL); sigaction(SIGHUP, &new_action, NULL);
sigaction(SIGTERM, &new_action, NULL); sigaction(SIGTERM, &new_action, NULL);
@ -423,6 +423,10 @@ void Util::Config::signal_handler(int signum, siginfo_t * sigInfo, void * ignore
case SIGHUP: case SIGHUP:
case SIGTERM: case SIGTERM:
if (serv_sock_pointer){serv_sock_pointer->close();} if (serv_sock_pointer){serv_sock_pointer->close();}
#if DEBUG >= DLVL_DEVEL
static int ctr = 0;
if (!is_active && ++ctr > 4){BACKTRACE;}
#endif
is_active = false; is_active = false;
default: default:
switch (sigInfo->si_code){ switch (sigInfo->si_code){

View file

@ -93,6 +93,7 @@ namespace IPC {
#else #else
mySem = SEM_FAILED; mySem = SEM_FAILED;
#endif #endif
isLocked = false;
} }
///\brief Constructs a named semaphore ///\brief Constructs a named semaphore
@ -106,6 +107,7 @@ namespace IPC {
#else #else
mySem = SEM_FAILED; mySem = SEM_FAILED;
#endif #endif
isLocked = false;
open(name, oflag, mode, value, noWait); open(name, oflag, mode, value, noWait);
} }
@ -178,9 +180,9 @@ namespace IPC {
} }
#endif #endif
} }
if (!(*this)) { if (*this) {
myName = (char *)name;
} }
myName = (char *)name;
} }
///\brief Returns the current value of the semaphore ///\brief Returns the current value of the semaphore
@ -197,12 +199,20 @@ namespace IPC {
///\brief Posts to the semaphore, increases its value by one ///\brief Posts to the semaphore, increases its value by one
void semaphore::post() { void semaphore::post() {
if (!*this || !isLocked){
FAIL_MSG("Attempted to unlock a non-locked semaphore: '%s'!", myName.c_str());
#if DEBUG >= DLVL_DEVEL
BACKTRACE;
#endif
return;
}
if (*this) { if (*this) {
#if defined(__CYGWIN__) || defined(_WIN32) #if defined(__CYGWIN__) || defined(_WIN32)
ReleaseMutex(mySem); ReleaseMutex(mySem);
#else #else
sem_post(mySem); sem_post(mySem);
#endif #endif
isLocked = false;
} }
} }
@ -217,6 +227,7 @@ namespace IPC {
tmp = sem_wait(mySem); tmp = sem_wait(mySem);
} while (tmp == -1 && errno == EINTR); } while (tmp == -1 && errno == EINTR);
#endif #endif
isLocked = true;
} }
} }
@ -235,7 +246,7 @@ namespace IPC {
result = sem_trywait(mySem); result = sem_trywait(mySem);
} while (result == -1 && errno == EINTR); } while (result == -1 && errno == EINTR);
#endif #endif
return (result == 0); return isLocked = (result == 0);
} }
///\brief Tries to wait for the semaphore for a single second, returns true if successful, false otherwise ///\brief Tries to wait for the semaphore for a single second, returns true if successful, false otherwise
@ -254,6 +265,7 @@ namespace IPC {
long long unsigned int timeout = now + 1e6; long long unsigned int timeout = now + 1e6;
while (now < timeout) { while (now < timeout) {
if (0 == sem_trywait(mySem)) { if (0 == sem_trywait(mySem)) {
isLocked = true;
return true; return true;
} }
usleep(100e3); usleep(100e3);
@ -266,12 +278,28 @@ namespace IPC {
wt.tv_nsec = 0; wt.tv_nsec = 0;
result = sem_timedwait(mySem, &wt); result = sem_timedwait(mySem, &wt);
#endif #endif
return (result == 0); return isLocked = (result == 0);
} }
///\brief Closes the currently opened semaphore ///\brief Closes the currently opened semaphore
void semaphore::close() { void semaphore::close() {
if (*this) { if (*this) {
if (isLocked){post();}
#if defined(__CYGWIN__) || defined(_WIN32)
CloseHandle(mySem);
mySem = 0;
#else
sem_close(mySem);
mySem = SEM_FAILED;
#endif
}
myName.clear();
}
/// Closes the semaphore, without unlocking it first.
/// Intended to be called from forked child processes, to drop the reference to the semaphore.
void semaphore::abandon() {
if (*this) {
#if defined(__CYGWIN__) || defined(_WIN32) #if defined(__CYGWIN__) || defined(_WIN32)
CloseHandle(mySem); CloseHandle(mySem);
mySem = 0; mySem = 0;
@ -280,19 +308,28 @@ namespace IPC {
mySem = SEM_FAILED; mySem = SEM_FAILED;
#endif #endif
} }
}
///\brief Unlinks the previously opened semaphore
void semaphore::unlink() {
close();
#if !defined(__CYGWIN__) && !defined(_WIN32)
if (myName.size()) {
sem_unlink(myName.c_str());
}
#endif
myName.clear(); myName.clear();
} }
/// Unlinks the previously opened semaphore, closing it (if open) in the process.
void semaphore::unlink() {
#if defined(__CYGWIN__) || defined(_WIN32)
if (isLocked){post();}
#endif
#if !defined(__CYGWIN__) && !defined(_WIN32)
if (myName.size()){sem_unlink(myName.c_str());}
#endif
if (*this) {
#if defined(__CYGWIN__) || defined(_WIN32)
CloseHandle(mySem);
mySem = 0;
#else
sem_close(mySem);
mySem = SEM_FAILED;
#endif
}
myName.clear();
}
#if defined(__CYGWIN__) || defined(_WIN32) #if defined(__CYGWIN__) || defined(_WIN32)
SECURITY_ATTRIBUTES semaphore::getSecurityAttributes() { SECURITY_ATTRIBUTES semaphore::getSecurityAttributes() {
@ -368,7 +405,7 @@ namespace IPC {
///\brief Unmaps a shared page if allowed ///\brief Unmaps a shared page if allowed
void sharedPage::unmap() { void sharedPage::unmap() {
if (mapped && len) { if (mapped) {
#if defined(__CYGWIN__) || defined(_WIN32) #if defined(__CYGWIN__) || defined(_WIN32)
//under Cygwin, the mapped location is shifted by 4 to contain the page size. //under Cygwin, the mapped location is shifted by 4 to contain the page size.
UnmapViewOfFile(mapped - 4); UnmapViewOfFile(mapped - 4);
@ -795,26 +832,19 @@ namespace IPC {
baseName = "/" + name; baseName = "/" + name;
payLen = len; payLen = len;
hasCounter = withCounter; hasCounter = withCounter;
mySemaphore.open(baseName.c_str(), O_CREAT | O_EXCL | O_RDWR, ACCESSPERMS, 1); mySemaphore.open(baseName.c_str(), O_CREAT | O_RDWR, ACCESSPERMS, 1);
if (!mySemaphore) {
mySemaphore.open(baseName.c_str(), O_CREAT | O_RDWR, ACCESSPERMS, 1);
}
if (!mySemaphore) { if (!mySemaphore) {
DEBUG_MSG(DLVL_FAIL, "Creating semaphore failed: %s", strerror(errno)); DEBUG_MSG(DLVL_FAIL, "Creating semaphore failed: %s", strerror(errno));
return; return;
}else{
semGuard tmpGuard(&mySemaphore);
amount = 0;
newPage();
} }
if (!mySemaphore.tryWaitOneSecond()){
WARN_MSG("Force unlocking sharedServer semaphore to prevent deadlock");
}
mySemaphore.post();
semGuard tmpGuard(&mySemaphore);
amount = 0;
newPage();
} }
///\brief The deconstructor ///\brief The deconstructor
sharedServer::~sharedServer() { sharedServer::~sharedServer() {
mySemaphore.close();
mySemaphore.unlink(); mySemaphore.unlink();
} }
@ -1251,7 +1281,7 @@ namespace IPC {
if (!hasCounter) { if (!hasCounter) {
return (myPage.mapped != 0); return (myPage.mapped != 0);
} }
if (myPage.mapped){ if (myPage.mapped && offsetOnPage >= 0){
return (myPage.mapped[offsetOnPage] & 0x7F) < 60; return (myPage.mapped[offsetOnPage] & 0x7F) < 60;
} }
return false; return false;

View file

@ -75,6 +75,7 @@ namespace IPC {
bool tryWait(); bool tryWait();
bool tryWaitOneSecond(); bool tryWaitOneSecond();
void close(); void close();
void abandon();
void unlink(); void unlink();
private: private:
#if defined(__CYGWIN__) || defined(_WIN32) #if defined(__CYGWIN__) || defined(_WIN32)
@ -84,6 +85,7 @@ namespace IPC {
#else #else
sem_t * mySem; sem_t * mySem;
#endif #endif
bool isLocked;
std::string myName; std::string myName;
}; };

View file

@ -83,7 +83,8 @@ void statusMonitor(void *np){
WARN_MSG("Configuration semaphore was stuck. Force-unlocking it and re-writing config."); WARN_MSG("Configuration semaphore was stuck. Force-unlocking it and re-writing config.");
changed = true; changed = true;
} }
configLock.post(); configLock.unlink();
configLock.open(SEM_CONF, O_CREAT | O_RDWR, ACCESSPERMS, 1);
if (changed || Controller::configChanged){ if (changed || Controller::configChanged){
Controller::writeConfig(); Controller::writeConfig();
Controller::configChanged = false; Controller::configChanged = false;

View file

@ -109,41 +109,77 @@ namespace Mist {
} }
IPC::semaphore playerLock; IPC::semaphore playerLock;
if (needsLock() && streamName.size()){ IPC::semaphore pullLock;
char semName[NAME_BUFFER_SIZE];
snprintf(semName, NAME_BUFFER_SIZE, SEM_INPUT, streamName.c_str()); //If we're not converting, we might need a lock.
playerLock.open(semName, O_CREAT | O_RDWR, ACCESSPERMS, 1); if (streamName.size()){
if (!playerLock.tryWait()){ if (needsLock()){
DEBUG_MSG(DLVL_DEVEL, "A player for stream %s is already running", streamName.c_str()); //needsLock() == true means this input is the sole responsible input for a stream
return 1; //That means it's MistInBuffer for live, or the actual input binary for VoD
//For these cases, we lock the SEM_INPUT semaphore.
char semName[NAME_BUFFER_SIZE];
snprintf(semName, NAME_BUFFER_SIZE, SEM_INPUT, streamName.c_str());
playerLock.open(semName, O_CREAT | O_RDWR, ACCESSPERMS, 1);
if (!playerLock.tryWait()){
INFO_MSG("A player for stream %s is already running", streamName.c_str());
playerLock.close();
return 1;
}
char pageName[NAME_BUFFER_SIZE];
snprintf(pageName, NAME_BUFFER_SIZE, SHM_STREAM_STATE, streamName.c_str());
streamStatus.init(pageName, 1, true, false);
if (streamStatus){streamStatus.mapped[0] = STRMSTAT_INIT;}
streamStatus.master = false;
streamStatus.close();
}else{
//needsLock() == false means this binary will itself start the sole responsible input
//So, we definitely do NOT lock SEM_INPUT, since the child process will do that later.
//However, most of these processes are singular, meaning they expect to be the only source of data.
//To prevent multiple singular processes starting, we use the MstPull semaphore if this input
//is indeed a singular input type.
if (isSingular()){
pullLock.open(std::string("/MstPull_" + streamName).c_str(), O_CREAT | O_RDWR, ACCESSPERMS, 1);
if (!pullLock){
FAIL_MSG("Could not open pull lock for stream '%s' - aborting!", streamName.c_str());
return 1;
}
if (!pullLock.tryWait()){
WARN_MSG("A pull process for stream %s is already running", streamName.c_str());
pullLock.close();
return 1;
}
}
} }
char pageName[NAME_BUFFER_SIZE];
snprintf(pageName, NAME_BUFFER_SIZE, SHM_STREAM_STATE, streamName.c_str());
streamStatus.init(pageName, 1, true, false);
if (streamStatus){streamStatus.mapped[0] = STRMSTAT_INIT;}
streamStatus.master = false;
streamStatus.close();
} }
config->activate(); config->activate();
uint64_t reTimer = 0; uint64_t reTimer = 0;
while (config->is_active){ while (config->is_active){
pid_t pid = fork(); pid_t pid = fork();
if (pid == 0){ if (pid == 0){
//Re-init streamStatus, previously closed if (playerLock){
char pageName[NAME_BUFFER_SIZE]; //Re-init streamStatus, previously closed
snprintf(pageName, NAME_BUFFER_SIZE, SHM_STREAM_STATE, streamName.c_str()); char pageName[NAME_BUFFER_SIZE];
streamStatus.init(pageName, 1, true, false); snprintf(pageName, NAME_BUFFER_SIZE, SHM_STREAM_STATE, streamName.c_str());
streamStatus.master = false; streamStatus.init(pageName, 1, true, false);
if (streamStatus){streamStatus.mapped[0] = STRMSTAT_INIT;} streamStatus.master = false;
if (needsLock()){playerLock.close();} if (streamStatus){streamStatus.mapped[0] = STRMSTAT_INIT;}
}
//Abandon all semaphores, ye who enter here.
playerLock.abandon();
pullLock.abandon();
if (!preRun()){return 0;} if (!preRun()){return 0;}
return run(); return run();
} }
if (pid == -1){ if (pid == -1){
FAIL_MSG("Unable to spawn input process"); FAIL_MSG("Unable to spawn input process");
if (needsLock()){playerLock.post();} //We failed. Release the kra... semaphores!
//post() contains an is-open check already, no need to double-check.
playerLock.unlink();
pullLock.unlink();
return 2; return 2;
} }
HIGH_MSG("Waiting for child for stream %s", streamName.c_str());
//wait for the process to exit //wait for the process to exit
int status; int status;
while (waitpid(pid, &status, 0) != pid && errno == EINTR){ while (waitpid(pid, &status, 0) != pid && errno == EINTR){
@ -153,35 +189,38 @@ namespace Mist {
} }
continue; continue;
} }
HIGH_MSG("Done waiting for child for stream %s", streamName.c_str());
//if the exit was clean, don't restart it //if the exit was clean, don't restart it
if (WIFEXITED(status) && (WEXITSTATUS(status) == 0)){ if (WIFEXITED(status) && (WEXITSTATUS(status) == 0)){
INFO_MSG("Input for stream %s shut down cleanly", streamName.c_str()); INFO_MSG("Input for stream %s shut down cleanly", streamName.c_str());
break; break;
} }
char pageName[NAME_BUFFER_SIZE]; if (playerLock){
snprintf(pageName, NAME_BUFFER_SIZE, SHM_STREAM_STATE, streamName.c_str()); char pageName[NAME_BUFFER_SIZE];
streamStatus.init(pageName, 1, true, false); snprintf(pageName, NAME_BUFFER_SIZE, SHM_STREAM_STATE, streamName.c_str());
if (streamStatus){streamStatus.mapped[0] = STRMSTAT_INVALID;} streamStatus.init(pageName, 1, true, false);
if (streamStatus){streamStatus.mapped[0] = STRMSTAT_INVALID;}
}
#if DEBUG >= DLVL_DEVEL #if DEBUG >= DLVL_DEVEL
WARN_MSG("Aborting autoclean; this is a development build."); WARN_MSG("Input for stream %s uncleanly shut down! Aborting restart; this is a development build.", streamName.c_str());
INFO_MSG("Input for stream %s uncleanly shut down! Aborting restart; this is a development build.", streamName.c_str());
break; break;
#else #else
WARN_MSG("Input for stream %s uncleanly shut down! Restarting...", streamName.c_str());
onCrash(); onCrash();
INFO_MSG("Input for stream %s uncleanly shut down! Restarting...", streamName.c_str());
Util::wait(reTimer); Util::wait(reTimer);
reTimer += 1000; reTimer += 1000;
#endif #endif
} }
if (needsLock()){
playerLock.post(); if (playerLock){
playerLock.unlink(); playerLock.unlink();
playerLock.close(); char pageName[NAME_BUFFER_SIZE];
snprintf(pageName, NAME_BUFFER_SIZE, SHM_STREAM_STATE, streamName.c_str());
streamStatus.init(pageName, 1, true, false);
streamStatus.close();
} }
char pageName[NAME_BUFFER_SIZE]; pullLock.unlink();
snprintf(pageName, NAME_BUFFER_SIZE, SHM_STREAM_STATE, streamName.c_str());
streamStatus.init(pageName, 1, true, false);
streamStatus.close();
HIGH_MSG("Angel process for %s exiting", streamName.c_str()); HIGH_MSG("Angel process for %s exiting", streamName.c_str());
return 0; return 0;
} }
@ -207,29 +246,21 @@ namespace Mist {
} }
if (!streamName.size()) { if (!streamName.size()) {
//If we don't have a stream name, that means we're in stand-alone conversion mode.
MEDIUM_MSG("Starting convert"); MEDIUM_MSG("Starting convert");
convert(); convert();
} else if (!needsLock()) { } else if (!needsLock()) {
//We have a name and aren't the sole process. That means we're streaming live data to a buffer.
MEDIUM_MSG("Starting stream"); MEDIUM_MSG("Starting stream");
stream(); stream();
}else{ }else{
//We are the sole process and have a name. That means this is a Buffer or VoD input.
MEDIUM_MSG("Starting serve"); MEDIUM_MSG("Starting serve");
serve(); serve();
} }
return 0; return 0;
} }
/// Default crash handler, cleans up Pull semaphore on crashes
void Input::onCrash(){
if (streamName.size() && !needsLock()) {
//we have a Pull semaphore to clean up, do it
IPC::semaphore pullLock;
pullLock.open(std::string("/MstPull_" + streamName).c_str(), O_CREAT | O_RDWR, ACCESSPERMS, 1);
pullLock.close();
pullLock.unlink();
}
}
void Input::convert() { void Input::convert() {
//check filename for no - //check filename for no -
if (config->getString("output") != "-"){ if (config->getString("output") != "-"){
@ -296,7 +327,7 @@ namespace Mist {
userPage.init(userPageName, PLAY_EX_SIZE, true); userPage.init(userPageName, PLAY_EX_SIZE, true);
if (streamStatus){streamStatus.mapped[0] = STRMSTAT_READY;} if (streamStatus){streamStatus.mapped[0] = STRMSTAT_READY;}
DEBUG_MSG(DLVL_DEVEL, "Input for stream %s started", streamName.c_str()); INFO_MSG("Input for stream %s started", streamName.c_str());
activityCounter = Util::bootSecs(); activityCounter = Util::bootSecs();
//main serve loop //main serve loop
while (keepRunning()) { while (keepRunning()) {
@ -321,7 +352,7 @@ namespace Mist {
if (streamStatus){streamStatus.mapped[0] = STRMSTAT_SHUTDOWN;} if (streamStatus){streamStatus.mapped[0] = STRMSTAT_SHUTDOWN;}
config->is_active = false; config->is_active = false;
finish(); finish();
DEBUG_MSG(DLVL_DEVEL, "Input for stream %s closing clean", streamName.c_str()); INFO_MSG("Input for stream %s closing clean", streamName.c_str());
userPage.finishEach(); userPage.finishEach();
//end player functionality //end player functionality
} }
@ -352,27 +383,10 @@ namespace Mist {
/// - if there are tracks, register as a non-viewer on the user page of the buffer /// - if there are tracks, register as a non-viewer on the user page of the buffer
/// - call getNext() in a loop, buffering packets /// - call getNext() in a loop, buffering packets
void Input::stream(){ void Input::stream(){
IPC::semaphore pullLock;
if(isSingular()){
pullLock.open(std::string("/MstPull_" + streamName).c_str(), O_CREAT | O_RDWR, ACCESSPERMS, 1);
if (!pullLock){
FAIL_MSG("Could not open pull lock for stream '%s' - aborting!", streamName.c_str());
return;
}
if (!pullLock.tryWait()){ if (Util::streamAlive(streamName)){
WARN_MSG("A pull process for stream %s is already running", streamName.c_str()); WARN_MSG("Stream already online, cancelling");
pullLock.close(); return;
return;
}
if (Util::streamAlive(streamName)){
pullLock.post();
pullLock.close();
pullLock.unlink();
WARN_MSG("Stream already online, cancelling");
return;
}
} }
std::map<std::string, std::string> overrides; std::map<std::string, std::string> overrides;
@ -382,11 +396,6 @@ namespace Mist {
} }
if (!Util::startInput(streamName, "push://INTERNAL_ONLY:"+config->getString("input"), true, true, overrides)) {//manually override stream url to start the buffer if (!Util::startInput(streamName, "push://INTERNAL_ONLY:"+config->getString("input"), true, true, overrides)) {//manually override stream url to start the buffer
if(isSingular()){
pullLock.post();
pullLock.close();
pullLock.unlink();
}
WARN_MSG("Could not start buffer, cancelling"); WARN_MSG("Could not start buffer, cancelling");
return; return;
} }
@ -396,10 +405,6 @@ namespace Mist {
if (!openStreamSource()){ if (!openStreamSource()){
FAIL_MSG("Unable to connect to source"); FAIL_MSG("Unable to connect to source");
if(isSingular()){
pullLock.post();
pullLock.close();
}
return; return;
} }
@ -413,11 +418,6 @@ namespace Mist {
if (myMeta.tracks.size() == 0){ if (myMeta.tracks.size() == 0){
nProxy.userClient.finish(); nProxy.userClient.finish();
finish(); finish();
if(isSingular()){
pullLock.post();
pullLock.close();
pullLock.unlink();
}
INFO_MSG("No tracks found, cancelling"); INFO_MSG("No tracks found, cancelling");
return; return;
} }
@ -434,11 +434,6 @@ namespace Mist {
nProxy.userClient.finish(); nProxy.userClient.finish();
finish(); finish();
if(isSingular()){
pullLock.post();
pullLock.close();
pullLock.unlink();
}
INFO_MSG("Stream input %s closing clean; reason: %s", streamName.c_str(), reason.c_str()); INFO_MSG("Stream input %s closing clean; reason: %s", streamName.c_str(), reason.c_str());
return; return;
} }

View file

@ -20,7 +20,7 @@ namespace Mist {
public: public:
Input(Util::Config * cfg); Input(Util::Config * cfg);
virtual int run(); virtual int run();
virtual void onCrash(); virtual void onCrash(){}
virtual int boot(int argc, char * argv[]); virtual int boot(int argc, char * argv[]);
virtual ~Input() {}; virtual ~Input() {};

View file

@ -463,7 +463,7 @@ namespace Mist {
} }
//Track is set to "New track request", assign new track id and create shared memory page //Track is set to "New track request", assign new track id and create shared memory page
//This indicates that the 'current key' part of the element is set to contain the original track id from the pushing process //This indicates that the 'current key' part of the element is set to contain the original track id from the pushing process
if (value & 0x80000000) { if (config->is_active && (value & 0x80000000)) {
if (value & 0x40000000) { if (value & 0x40000000) {
unsigned long finalMap = value & ~0xC0000000; unsigned long finalMap = value & ~0xC0000000;
//Register the new track as an active track. //Register the new track as an active track.
@ -480,9 +480,15 @@ namespace Mist {
char tempMetaName[NAME_BUFFER_SIZE]; char tempMetaName[NAME_BUFFER_SIZE];
snprintf(tempMetaName, NAME_BUFFER_SIZE, SHM_TRACK_META, config->getString("streamname").c_str(), finalMap); snprintf(tempMetaName, NAME_BUFFER_SIZE, SHM_TRACK_META, config->getString("streamname").c_str(), finalMap);
tMeta.init(tempMetaName, 8388608, false); tMeta.init(tempMetaName, 8388608, false, false);
if (!tMeta){continue;}//abort for now if page doesn't exist yet
//The page exist, now we try to read in the metadata of the track char firstPage[NAME_BUFFER_SIZE];
snprintf(firstPage, NAME_BUFFER_SIZE, SHM_TRACK_INDEX, config->getString("streamname").c_str(), finalMap);
nProxy.metaPages[finalMap].init(firstPage, SHM_TRACK_INDEX_SIZE, false, false);
if (!nProxy.metaPages[finalMap]){continue;}//abort for now if page doesn't exist yet
//The pages exist, now we try to read in the metadata of the track
//Store the size of the dtsc packet to read. //Store the size of the dtsc packet to read.
unsigned int len = ntohl(((int *)tMeta.mapped)[1]); unsigned int len = ntohl(((int *)tMeta.mapped)[1]);
@ -505,11 +511,6 @@ namespace Mist {
userConn.setTrackId(index, finalMap); userConn.setTrackId(index, finalMap);
userConn.setKeynum(index, 0x0000); userConn.setKeynum(index, 0x0000);
char firstPage[NAME_BUFFER_SIZE];
snprintf(firstPage, NAME_BUFFER_SIZE, SHM_TRACK_INDEX, config->getString("streamname").c_str(), finalMap);
nProxy.metaPages[finalMap].init(firstPage, SHM_TRACK_INDEX_SIZE, false);
//Update the metadata for this track //Update the metadata for this track
updateTrackMeta(finalMap); updateTrackMeta(finalMap);
hasPush = true; hasPush = true;
@ -536,7 +537,7 @@ namespace Mist {
} }
//The track id is set to the value of a track that we are currently negotiating about //The track id is set to the value of a track that we are currently negotiating about
if (negotiatingTracks.count(value)) { if (config->is_active && negotiatingTracks.count(value)) {
//If the metadata page for this track is not yet registered, initialize it //If the metadata page for this track is not yet registered, initialize it
if (!nProxy.metaPages.count(value) || !nProxy.metaPages[value].mapped) { if (!nProxy.metaPages.count(value) || !nProxy.metaPages[value].mapped) {
char tempMetaName[NAME_BUFFER_SIZE]; char tempMetaName[NAME_BUFFER_SIZE];
@ -740,7 +741,10 @@ namespace Mist {
strName = strName.substr(0, (strName.find_first_of("+ "))); strName = strName.substr(0, (strName.find_first_of("+ ")));
IPC::sharedPage serverCfg(SHM_CONF, DEFAULT_CONF_PAGE_SIZE, false, false); ///< Contains server configuration and capabilities IPC::sharedPage serverCfg(SHM_CONF, DEFAULT_CONF_PAGE_SIZE, false, false); ///< Contains server configuration and capabilities
IPC::semaphore configLock(SEM_CONF, O_CREAT | O_RDWR, ACCESSPERMS, 1); IPC::semaphore configLock(SEM_CONF, O_CREAT | O_RDWR, ACCESSPERMS, 1);
configLock.wait(); if (!configLock.tryWaitOneSecond()){
INFO_MSG("Aborting stream config refresh: locking took longer than expected");
return false;
}
DTSC::Scan streamCfg = DTSC::Scan(serverCfg.mapped, serverCfg.len).getMember("streams").getMember(strName); DTSC::Scan streamCfg = DTSC::Scan(serverCfg.mapped, serverCfg.len).getMember("streams").getMember(strName);
long long tmpNum; long long tmpNum;
@ -783,8 +787,6 @@ namespace Mist {
resumeMode = tmpNum; resumeMode = tmpNum;
} }
configLock.post();
configLock.close();
return true; return true;
} }