Browse Source

Merge pull request #646 from paullouisageneau/fix-sctp-bad-weak-ptr

Fix unhandled bad_weak_ptr exception on SCTP transport destruction
Paul-Louis Ageneau 3 years ago
parent
commit
563bb32349
1 changed files with 31 additions and 25 deletions
  1. 31 25
      src/impl/sctptransport.cpp

+ 31 - 25
src/impl/sctptransport.cpp

@@ -187,9 +187,6 @@ SctpTransport::SctpTransport(shared_ptr<Transport> lower, const Configuration &c
 
 
 	PLOG_DEBUG << "Initializing SCTP transport";
 	PLOG_DEBUG << "Initializing SCTP transport";
 
 
-	usrsctp_register_address(this);
-	Instances->insert(this);
-
 	mSock = usrsctp_socket(AF_CONN, SOCK_STREAM, IPPROTO_SCTP, nullptr, nullptr, 0, nullptr);
 	mSock = usrsctp_socket(AF_CONN, SOCK_STREAM, IPPROTO_SCTP, nullptr, nullptr, 0, nullptr);
 	if (!mSock)
 	if (!mSock)
 		throw std::runtime_error("Could not create SCTP socket, errno=" + std::to_string(errno));
 		throw std::runtime_error("Could not create SCTP socket, errno=" + std::to_string(errno));
@@ -323,14 +320,14 @@ SctpTransport::SctpTransport(shared_ptr<Transport> lower, const Configuration &c
 	if (usrsctp_setsockopt(mSock, SOL_SOCKET, SO_SNDBUF, &sndBuf, sizeof(sndBuf)))
 	if (usrsctp_setsockopt(mSock, SOL_SOCKET, SO_SNDBUF, &sndBuf, sizeof(sndBuf)))
 		throw std::runtime_error("Could not set SCTP send buffer size, errno=" +
 		throw std::runtime_error("Could not set SCTP send buffer size, errno=" +
 		                         std::to_string(errno));
 		                         std::to_string(errno));
+
+	usrsctp_register_address(this);
+	Instances->insert(this);
 }
 }
 
 
 SctpTransport::~SctpTransport() {
 SctpTransport::~SctpTransport() {
 	stop();
 	stop();
 	close();
 	close();
-
-	usrsctp_deregister_address(this);
-	Instances->erase(this);
 }
 }
 
 
 void SctpTransport::start() {
 void SctpTransport::start() {
@@ -355,14 +352,6 @@ bool SctpTransport::stop() {
 	return true;
 	return true;
 }
 }
 
 
-void SctpTransport::close() {
-	if (mSock) {
-		mProcessor.join();
-		usrsctp_close(mSock);
-		mSock = nullptr;
-	}
-}
-
 struct sockaddr_conn SctpTransport::getSockAddrConn(uint16_t port) {
 struct sockaddr_conn SctpTransport::getSockAddrConn(uint16_t port) {
 	struct sockaddr_conn sconn = {};
 	struct sockaddr_conn sconn = {};
 	sconn.sconn_family = AF_CONN;
 	sconn.sconn_family = AF_CONN;
@@ -412,6 +401,18 @@ void SctpTransport::shutdown() {
 	mWrittenCondition.notify_all();
 	mWrittenCondition.notify_all();
 }
 }
 
 
+void SctpTransport::close() {
+	if (!mSock)
+		return;
+
+	usrsctp_deregister_address(this);
+	Instances->erase(this);
+
+	mProcessor.join();
+	usrsctp_close(mSock);
+	mSock = nullptr;
+}
+
 bool SctpTransport::send(message_ptr message) {
 bool SctpTransport::send(message_ptr message) {
 	std::lock_guard lock(mSendMutex);
 	std::lock_guard lock(mSendMutex);
 
 
@@ -701,21 +702,26 @@ void SctpTransport::sendReset(uint16_t streamId) {
 }
 }
 
 
 void SctpTransport::handleUpcall() {
 void SctpTransport::handleUpcall() {
-	if (!mSock)
-		return;
+	try {
+		if (!mSock)
+			return;
 
 
-	PLOG_VERBOSE << "Handle upcall";
+		PLOG_VERBOSE << "Handle upcall";
 
 
-	int events = usrsctp_get_events(mSock);
+		int events = usrsctp_get_events(mSock);
 
 
-	if (events & SCTP_EVENT_READ && mPendingRecvCount == 0) {
-		++mPendingRecvCount;
-		mProcessor.enqueue(&SctpTransport::doRecv, shared_from_this());
-	}
+		if (events & SCTP_EVENT_READ && mPendingRecvCount == 0) {
+			++mPendingRecvCount;
+			mProcessor.enqueue(&SctpTransport::doRecv, shared_from_this());
+		}
 
 
-	if (events & SCTP_EVENT_WRITE && mPendingFlushCount == 0) {
-		++mPendingFlushCount;
-		mProcessor.enqueue(&SctpTransport::doFlush, shared_from_this());
+		if (events & SCTP_EVENT_WRITE && mPendingFlushCount == 0) {
+			++mPendingFlushCount;
+			mProcessor.enqueue(&SctpTransport::doFlush, shared_from_this());
+		}
+
+	} catch (const std::exception &e) {
+		PLOG_ERROR << "SCTP upcall: " << e.what();
 	}
 	}
 }
 }