diff --git a/server/Makefile b/server/Makefile index f10e89c4..e0c148a9 100644 --- a/server/Makefile +++ b/server/Makefile @@ -31,11 +31,12 @@ else endif # Simplify building debuggable executables 'make DEBUG=-g STRIP=echo' -DEBUG=-O3 +DEBUG=-O2 +SANITIZE= +#-fsanitize=thread - -CXXFLAGS += $(ADD_CFLAGS) -std=c++14 -Wall -Wpedantic -Wno-unused-function $(DEBUG) -DHAS_FLAC -DHAS_OGG -DHAS_VORBIS -DHAS_VORBIS_ENC -DVERSION=\"$(VERSION)\" -I. -I.. -I../common -LDFLAGS = $(ADD_LDFLAGS) -lvorbis -lvorbisenc -logg -lFLAC +CXXFLAGS += $(ADD_CFLAGS) $(SANITIZE) -std=c++14 -Wall -Wpedantic -Wno-unused-function $(DEBUG) -DHAS_FLAC -DHAS_OGG -DHAS_VORBIS -DHAS_VORBIS_ENC -DVERSION=\"$(VERSION)\" -I. -I.. -I../common +LDFLAGS = $(ADD_LDFLAGS) $(SANITIZE) -lvorbis -lvorbisenc -logg -lFLAC OBJ = snapserver.o config.o control_server.o control_session_tcp.o control_session_http.o stream_server.o stream_session.o streamreader/streamUri.o streamreader/base64.o streamreader/streamManager.o streamreader/pcmStream.o streamreader/pipeStream.o streamreader/fileStream.o streamreader/processStream.o streamreader/airplayStream.o streamreader/spotifyStream.o streamreader/watchdog.o encoder/encoderFactory.o encoder/flacEncoder.o encoder/pcmEncoder.o encoder/oggEncoder.o ../common/sampleFormat.o ifneq (,$(TARGET)) diff --git a/server/control_server.cpp b/server/control_server.cpp index f59c56f0..4a76fd32 100644 --- a/server/control_server.cpp +++ b/server/control_server.cpp @@ -47,23 +47,19 @@ ControlServer::~ControlServer() void ControlServer::cleanup() { - std::lock_guard mlock(session_mutex_); - for (auto it = sessions_.begin(); it != sessions_.end();) + auto new_end = std::remove_if(sessions_.begin(), sessions_.end(), [](std::weak_ptr session) { return session.expired(); }); + auto count = distance(new_end, sessions_.end()); + if (count > 0) { - if (it->expired()) - { - SLOG(ERROR) << "Session inactive. Removing\n"; - sessions_.erase(it++); - } - else - ++it; + SLOG(ERROR) << "Removing " << count << " inactive session(s), active sessions: " << sessions_.size() - count << "\n"; + sessions_.erase(new_end, sessions_.end()); } } void ControlServer::send(const std::string& message, const ControlSession* excludeSession) { - cleanup(); + std::lock_guard mlock(session_mutex_); for (auto s : sessions_) { if (auto session = s.lock()) @@ -72,6 +68,7 @@ void ControlServer::send(const std::string& message, const ControlSession* exclu session->sendAsync(message); } } + cleanup(); } @@ -203,6 +200,7 @@ void ControlServer::stop() cancel_accept(acceptor_http_.first.get()); cancel_accept(acceptor_http_.second.get()); std::lock_guard mlock(session_mutex_); + cleanup(); for (auto s : sessions_) { if (auto session = s.lock()) diff --git a/server/snapserver.conf b/server/snapserver.conf index 2258c64c..06aea0c1 100644 --- a/server/snapserver.conf +++ b/server/snapserver.conf @@ -12,7 +12,7 @@ ############################################################################### # default values are commented -# uncomment to change them +# uncomment and edit to change them # HTTP RPC #################################################################### diff --git a/server/stream_session.cpp b/server/stream_session.cpp index 24149229..d34533d2 100644 --- a/server/stream_session.cpp +++ b/server/stream_session.cpp @@ -75,12 +75,15 @@ void StreamSession::stop() try { boost::system::error_code ec; - socket_.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec); - if (ec) - LOG(ERROR) << "Error in socket shutdown: " << ec.message() << "\n"; - socket_.close(ec); - if (ec) - LOG(ERROR) << "Error in socket close: " << ec.message() << "\n"; + { + std::lock_guard socketLock(socketMutex_); + socket_.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec); + if (ec) + LOG(ERROR) << "Error in socket shutdown: " << ec.message() << "\n"; + socket_.close(ec); + if (ec) + LOG(ERROR) << "Error in socket close: " << ec.message() << "\n"; + } if (readerThread_ && readerThread_->joinable()) { LOG(DEBUG) << "StreamSession joining readerThread\n"; @@ -145,10 +148,12 @@ bool StreamSession::send(const msg::message_ptr& message) { // TODO on exception: set active = false // LOG(INFO) << "send: " << message->type << ", size: " << message->getSize() << ", id: " << message->id << ", refers: " << message->refersTo << "\n"; - std::lock_guard activeLock(activeMutex_); - if (!active_) - return false; - + std::lock_guard socketLock(socketMutex_); + { + std::lock_guard activeLock(activeMutex_); + if (!active_) + return false; + } boost::asio::streambuf streambuf; std::ostream stream(&streambuf); tv t;