Skip to content

Commit

Permalink
Proposed fix for deadlock on shutdown (#1673)
Browse files Browse the repository at this point in the history
* Proposed fix for deadlock on shutdown

* Terminate C style comment.

* Added needed libs for applicable tests and updated the logic for when allowing/disallowing connections.

* Need to load additional trick libs for applicable tests for Linux.

---------

Co-authored-by: Hong Chen <[email protected]>
  • Loading branch information
jmpenn and hchen99 authored Mar 28, 2024
1 parent 72e82e1 commit c4e60d9
Show file tree
Hide file tree
Showing 12 changed files with 66 additions and 23 deletions.
2 changes: 2 additions & 0 deletions include/trick/VariableServer.hh
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ namespace Trick {
*/
int freeze_init() ;

void shutdownConnections();

/**
@brief Shutdown the variable server
@return always 0
Expand Down
8 changes: 7 additions & 1 deletion include/trick/VariableServerListenThread.hh
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ namespace Trick {

virtual void dump( std::ostream & oss = std::cout ) ;

void shutdownConnections();

protected:
void initializeMulticast();

Expand All @@ -82,9 +84,13 @@ namespace Trick {
/* Multicast broadcaster */
MulticastGroup * _multicast; /**< trick_io(**) trick_units(--) */

bool allowConnections; /**< trick_io(**) trick_units(--) */
unsigned int pendingConnections; /**< trick_io(**) trick_units(--) */
pthread_mutex_t connectionMutex; /**< trick_io(**) trick_units(--) */
pthread_cond_t noPendingConnections_cv; /**< trick_io(**) trick_units(--) */

} ;

}

#endif

4 changes: 2 additions & 2 deletions trick_source/sim_services/Clock/test/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ include $(dir $(lastword $(MAKEFILE_LIST)))../../../../share/trick/makefiles/Mak

# Flags passed to the preprocessor.
TRICK_CPPFLAGS += -I$(GTEST_HOME)/include -I$(TRICK_HOME)/include -g -Wall -Wextra ${TRICK_SYSTEM_CXXFLAGS} ${TRICK_TEST_FLAGS}

TRICK_LIBS = -L${TRICK_LIB_DIR} -ltrick -ltrick_units -ltrick_mm -ltrick_pyip -ltrick_connection_handlers -ltrick_comm
LIBS = -L${GTEST_HOME}/lib64 -L${GTEST_HOME}/lib -lgtest -lgtest_main


Expand Down Expand Up @@ -41,7 +41,7 @@ GetTimeOfDayClock_test.o : GetTimeOfDayClock_test.cpp
$(TRICK_CXX) $(TRICK_CPPFLAGS) -c $<

GetTimeOfDayClock_test : ${GETTIMEOFDAY_CLOCK_OBJECTS}
$(TRICK_CXX) $(TRICK_SYSTEM_LDFLAGS) $(TRICK_CPPFLAGS) -o $@ $^ ${LIBS}
$(TRICK_CXX) $(TRICK_SYSTEM_LDFLAGS) $(TRICK_CPPFLAGS) -o $@ $^ $(TRICK_LIBS) ${LIBS}

exec_get_rt_nap_stub.o : exec_get_rt_nap_stub.cpp
$(TRICK_CXX) $(TRICK_CPPFLAGS) -c $<
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ TRICK_CXXFLAGS += -I$(GTEST_HOME)/include -I$(TRICK_HOME)/include -g -Wall -Wext
MM_OBJECTS = $(TRICK_HOME)/trick_source/sim_services/MemoryManager/object_${TRICK_HOST_CPU}/extract_bitfield.o \
$(TRICK_HOME)/trick_source/sim_services/MemoryManager/object_${TRICK_HOST_CPU}/extract_unsigned_bitfield.o

TRICK_LIBS = -L${TRICK_LIB_DIR} -ltrick_mm -ltrick_units -ltrick -ltrick_mm -ltrick_units -ltrick
TRICK_LIBS = -L${TRICK_LIB_DIR} -ltrick_mm -ltrick_units -ltrick -ltrick_mm -ltrick_units -ltrick -ltrick_pyip -ltrick_connection_handlers -ltrick_comm -ltrick_mm -ltrick_units -ltrick
TRICK_EXEC_LINK_LIBS += -L${GTEST_HOME}/lib64 -L${GTEST_HOME}/lib -lgtest -lgtest_main -lpthread


Expand Down
5 changes: 5 additions & 0 deletions trick_source/sim_services/Executive/Executive_shutdown.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
#include "trick/message_type.h"
#include "trick/release.h"
#include "trick/SysThread.hh"
#include "trick/VariableServer.hh"
extern Trick::VariableServer * the_vs ;

/**
@design
Expand Down Expand Up @@ -62,6 +64,9 @@ int Trick::Executive::shutdown() {
}
}

/* Stop new connections to the Variable Server. */
the_vs->shutdownConnections();

try {

/* Call the shutdown jobs. */
Expand Down
2 changes: 1 addition & 1 deletion trick_source/sim_services/Executive/test/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ COVERAGE_FLAGS += -fprofile-arcs -ftest-coverage -O0
# Flags passed to the preprocessor.
TRICK_CPPFLAGS += -I$(GTEST_HOME)/include -I$(TRICK_HOME)/include -g -Wall -Wextra ${TRICK_SYSTEM_CXXFLAGS} ${TRICK_TEST_FLAGS}

TRICK_LIBS = -L ${TRICK_LIB_DIR} -ltrick_mm -ltrick_units -ltrick
TRICK_LIBS = -L ${TRICK_LIB_DIR} -ltrick_mm -ltrick_units -ltrick -ltrick_pyip -ltrick_connection_handlers -ltrick_comm
TRICK_EXEC_LINK_LIBS += -L${GTEST_HOME}/lib64 -L${GTEST_HOME}/lib -lgtest -lgtest_main
TRICK_SYSTEM_LDFLAGS += ${COVERAGE_FLAGS}

Expand Down
2 changes: 1 addition & 1 deletion trick_source/sim_services/Integrator/test/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ include $(dir $(lastword $(MAKEFILE_LIST)))../../../../share/trick/makefiles/Mak
# Flags passed to the preprocessor.
TRICK_CPPFLAGS += -I$(GTEST_HOME)/include -I$(TRICK_HOME)/include -I${TRICK_HOME}/trick_source -I${TRICK_HOME}/include/trick/compat -g -Wall -Wextra -DUSE_ER7_UTILS_INTEGRATORS=1 -DTEST ${TRICK_SYSTEM_CXXFLAGS} ${TRICK_TEST_FLAGS}

TRICK_LIBS = -L${TRICK_LIB_DIR} -ltrick -ltrick_mm -ltrick_units -ltrick -ltrick_mm
TRICK_LIBS = -L${TRICK_LIB_DIR} -ltrick -ltrick_mm -ltrick_units -ltrick_mm -ltrick_pyip -ltrick_connection_handlers -ltrick_comm -ltrick_mm -ltrick_units -ltrick
TRICK_EXEC_LINK_LIBS += -L${GTEST_HOME}/lib64 -L${GTEST_HOME}/lib -lgtest -lgtest_main

# All tests produced by this Makefile. Remember to add new tests you
Expand Down
2 changes: 1 addition & 1 deletion trick_source/sim_services/MemoryManager/test/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ TRICK_SYSTEM_LDFLAGS += ${COVERAGE_FLAGS}

# Flags passed to the preprocessor.
TRICK_CPPFLAGS += -I$(GTEST_HOME)/include -I$(TRICK_HOME)/include -g -Wall -Wextra -Wno-sign-compare ${COVERAGE_FLAGS} ${TRICK_SYSTEM_CXXFLAGS} ${TRICK_TEST_FLAGS}
TRICK_LIBS = -L${TRICK_LIB_DIR} -ltrick_mm -ltrick_units -ltrick -ltrick_mm -ltrick_units -ltrick
TRICK_LIBS = -L${TRICK_LIB_DIR} -ltrick_mm -ltrick_units -ltrick -ltrick_mm -ltrick_units -ltrick -ltrick_connection_handlers -ltrick_pyip -ltrick -ltrick_comm
TRICK_EXEC_LINK_LIBS += -L${GTEST_HOME}/lib64 -L${GTEST_HOME}/lib -lgtest -lgtest_main -lpthread

# ==================================================================================
Expand Down
2 changes: 1 addition & 1 deletion trick_source/sim_services/ScheduledJobQueue/test/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ include $(dir $(lastword $(MAKEFILE_LIST)))../../../../share/trick/makefiles/Mak

# Flags passed to the preprocessor.
TRICK_CPPFLAGS += -I$(GTEST_HOME)/include -I$(TRICK_HOME)/include -g -Wall -Wextra ${TRICK_SYSTEM_CXXFLAGS} ${TRICK_TEST_FLAGS}
TRICK_LIBS = -L${TRICK_LIB_DIR} -ltrick_mm -ltrick_units -ltrick -ltrick_mm -ltrick_units -ltrick
TRICK_LIBS = -L${TRICK_LIB_DIR} -ltrick_mm -ltrick_units -ltrick -ltrick_mm -ltrick_units -ltrick -ltrick_pyip -ltrick_connection_handlers -ltrick_comm -ltrick
TRICK_EXEC_LINK_LIBS += -L${GTEST_HOME}/lib64 -L${GTEST_HOME}/lib -lgtest -lgtest_main

# All tests produced by this Makefile. Remember to add new tests you
Expand Down
2 changes: 1 addition & 1 deletion trick_source/sim_services/Timer/test/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ include $(dir $(lastword $(MAKEFILE_LIST)))../../../../share/trick/makefiles/Mak

# Flags passed to the preprocessor.
TRICK_CPPFLAGS += -I$(GTEST_HOME)/include -I$(TRICK_HOME)/include -g -Wall -Wextra ${TRICK_SYSTEM_CXXFLAGS} ${TRICK_TEST_FLAGS}
TRICK_LIBS = -L${TRICK_LIB_DIR} -ltrick -ltrick_units -ltrick_mm
TRICK_LIBS = -L${TRICK_LIB_DIR} -ltrick -ltrick_units -ltrick_mm -ltrick_pyip -ltrick_connection_handlers -ltrick_comm
TRICK_EXEC_LINK_LIBS += -L${GTEST_HOME}/lib64 -L${GTEST_HOME}/lib -lgtest -lgtest_main -lpthread

# All tests produced by this Makefile. Remember to add new tests you
Expand Down
4 changes: 4 additions & 0 deletions trick_source/sim_services/VariableServer/VariableServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ Trick::VariableServer::~VariableServer() {
the_vs = NULL;
}

void Trick::VariableServer::shutdownConnections() {
listen_thread.shutdownConnections();
}

std::ostream& Trick::operator<< (std::ostream& s, Trick::VariableServer& vs) {
std::map < pthread_t , VariableServerSessionThread * >::iterator it ;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ Trick::VariableServerListenThread::VariableServerListenThread(TCPClientListener
_listener = new TCPClientListener;
}

allowConnections = true;
pendingConnections = 0;
pthread_mutex_init( &connectionMutex, NULL);
pthread_cond_init( &noPendingConnections_cv, NULL);

cancellable = false;
}

Expand Down Expand Up @@ -142,7 +147,7 @@ void * Trick::VariableServerListenThread::thread_body() {
} else {
user_name = strdup(passp->pw_name) ;
}

_listener->setBlockMode(true);

if ( _broadcast ) {
Expand All @@ -160,18 +165,29 @@ void * Trick::VariableServerListenThread::thread_body() {
if (_listener->checkForNewConnections()) {

// Create a new thread to service this connection
VariableServerSessionThread * vst = new Trick::VariableServerSessionThread() ;
vst->set_connection(_listener->setUpNewConnection());
vst->copy_cpus(get_cpus()) ;
vst->create_thread() ;
ConnectionStatus status = vst->wait_for_accept() ;

if (status == CONNECTION_FAIL) {
// If the connection failed, the thread will exit.
// Make sure it joins fully before deleting the vst object
vst->join_thread();
delete vst;
if ( allowConnections) {
pthread_mutex_lock(&connectionMutex);
pendingConnections ++;

VariableServerSessionThread * vst = new Trick::VariableServerSessionThread() ;
vst->set_connection(_listener->setUpNewConnection());
vst->copy_cpus(get_cpus()) ;
vst->create_thread() ;
ConnectionStatus status = vst->wait_for_accept() ;

if (status == CONNECTION_FAIL) {
// If the connection failed, the thread will exit.
// Make sure it joins fully before deleting the vst object
vst->join_thread();
delete vst;
}
pendingConnections --;
if ( pendingConnections == 0 ) {
pthread_cond_signal( &noPendingConnections_cv );
}
pthread_mutex_unlock(&connectionMutex);
}

} else if ( _broadcast ) {
// Otherwise, broadcast on the multicast channel if enabled
char buf1[1024];
Expand All @@ -192,6 +208,17 @@ void * Trick::VariableServerListenThread::thread_body() {
return NULL ;
}

void Trick::VariableServerListenThread::shutdownConnections() {
pthread_mutex_lock(&connectionMutex);
allowConnections = false;
// if ANY connections are pending, then wait here until we’re notified that NO connections are pending.
if (pendingConnections > 0) {
allowConnections = true;
pthread_cond_wait( &noPendingConnections_cv, &connectionMutex);
}
pthread_mutex_unlock( &connectionMutex );
}

#include <fcntl.h>

int Trick::VariableServerListenThread::restart() {
Expand All @@ -210,7 +237,7 @@ int Trick::VariableServerListenThread::restart() {

_listener->disconnect();
ret = _listener->initialize(_requested_source_address, _requested_port);

if (ret != 0) {
message_publish(MSG_ERROR, "ERROR: Could not establish listen port %d for Variable Server. Aborting.\n", _requested_port);
return (-1);
Expand Down Expand Up @@ -250,4 +277,3 @@ void Trick::VariableServerListenThread::dump( std::ostream & oss ) {
oss << " broadcast = " << _broadcast << std::endl ;
Trick::ThreadBase::dump(oss) ;
}

0 comments on commit c4e60d9

Please sign in to comment.