Skip to content

Commit d102775

Browse files
committed
Fix start/stop race condition hang.
1 parent 19ac90d commit d102775

File tree

5 files changed

+38
-34
lines changed

5 files changed

+38
-34
lines changed

SerialPrograms/Source/CommonFramework/Globals.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ namespace PokemonAutomation{
2626
const bool IS_BETA_VERSION = true;
2727
const int PROGRAM_VERSION_MAJOR = 0;
2828
const int PROGRAM_VERSION_MINOR = 54;
29-
const int PROGRAM_VERSION_PATCH = 15;
29+
const int PROGRAM_VERSION_PATCH = 16;
3030

3131
const std::string PROGRAM_VERSION_BASE =
3232
"v" + std::to_string(PROGRAM_VERSION_MAJOR) +

SerialPrograms/Source/NintendoSwitch/Framework/NintendoSwitch_MultiSwitchProgramSession.cpp

Lines changed: 19 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,11 @@ namespace NintendoSwitch{
2525

2626
void MultiSwitchProgramSession::add_listener(Listener& listener){
2727
auto ScopeCheck = m_sanitizer.check_scope();
28-
WriteSpinLock lg(m_lock);
29-
m_listeners.insert(&listener);
28+
m_listeners.add(listener);
3029
}
3130
void MultiSwitchProgramSession::remove_listener(Listener& listener){
3231
auto ScopeCheck = m_sanitizer.check_scope();
33-
WriteSpinLock lg(m_lock);
34-
m_listeners.erase(&listener);
32+
m_listeners.remove(listener);
3533
}
3634

3735

@@ -100,7 +98,13 @@ void MultiSwitchProgramSession::run_program_instance(MultiSwitchProgramEnvironme
10098
);
10199
}
102100

103-
m_scope.store(&scope, std::memory_order_release);
101+
{
102+
std::lock_guard<std::mutex> lg(program_lock());
103+
if (current_state() != ProgramState::RUNNING){
104+
return;
105+
}
106+
m_scope.store(&scope, std::memory_order_release);
107+
}
104108

105109
try{
106110
m_option.instance().program(env, scope);
@@ -114,31 +118,28 @@ void MultiSwitchProgramSession::run_program_instance(MultiSwitchProgramEnvironme
114118
env.consoles[c].controller().cancel_all_commands();
115119
}catch (...){}
116120
}
121+
std::lock_guard<std::mutex> lg(program_lock());
117122
m_scope.store(nullptr, std::memory_order_release);
118123
throw;
119124
}
125+
126+
std::lock_guard<std::mutex> lg(program_lock());
120127
m_scope.store(nullptr, std::memory_order_release);
121128
}
122129
void MultiSwitchProgramSession::internal_stop_program(){
123130
auto ScopeCheck = m_sanitizer.check_scope();
124-
WriteSpinLock lg(m_lock);
125-
// size_t consoles = m_system.count();
126-
// for (size_t c = 0; c < consoles; c++){
127-
// m_system[c].serial_session().stop();
128-
// }
129-
CancellableScope* scope = m_scope.load(std::memory_order_acquire);
130-
if (scope != nullptr){
131-
scope->cancel(std::make_exception_ptr(ProgramCancelledException()));
131+
{
132+
std::lock_guard<std::mutex> lg(program_lock());
133+
CancellableScope* scope = m_scope.load(std::memory_order_acquire);
134+
if (scope != nullptr){
135+
scope->cancel(std::make_exception_ptr(ProgramCancelledException()));
136+
}
132137
}
133138

134139
// Wait for program thread to finish.
135140
while (m_scope.load(std::memory_order_acquire) != nullptr){
136141
pause();
137142
}
138-
139-
// for (size_t c = 0; c < consoles; c++){
140-
// m_system[c].serial_session().reset();
141-
// }
142143
}
143144
void MultiSwitchProgramSession::internal_run_program(){
144145
auto ScopeCheck = m_sanitizer.check_scope();
@@ -273,11 +274,8 @@ void MultiSwitchProgramSession::shutdown(){
273274
}
274275
void MultiSwitchProgramSession::startup(size_t switch_count){
275276
auto ScopeCheck = m_sanitizer.check_scope();
276-
WriteSpinLock lg(m_lock);
277277
m_option.instance().update_active_consoles(switch_count);
278-
for (Listener* listener : m_listeners){
279-
listener->redraw_options();
280-
}
278+
m_listeners.run_method_unique(&Listener::redraw_options);
281279
}
282280

283281

SerialPrograms/Source/NintendoSwitch/Framework/NintendoSwitch_MultiSwitchProgramSession.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,9 @@ class MultiSwitchProgramSession final : public ProgramSession, private MultiSwit
5959
MultiSwitchProgramOption& m_option;
6060
MultiSwitchSystemSession m_system;
6161

62-
SpinLock m_lock;
6362
std::atomic<CancellableScope*> m_scope;
6463

65-
std::set<Listener*> m_listeners;
64+
ListenerSet<Listener> m_listeners;
6665

6766
LifetimeSanitizer m_sanitizer;
6867
};

SerialPrograms/Source/NintendoSwitch/Framework/NintendoSwitch_SingleSwitchProgramSession.cpp

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,13 @@ void SingleSwitchProgramSession::run_program_instance(SingleSwitchProgramEnviron
7979
);
8080

8181
ControllerContext<AbstractController> context(scope, env.console.controller());
82-
m_scope.store(&context, std::memory_order_release);
82+
{
83+
std::lock_guard<std::mutex> lg(program_lock());
84+
if (current_state() != ProgramState::RUNNING){
85+
return;
86+
}
87+
m_scope.store(&context, std::memory_order_release);
88+
}
8389

8490
#ifdef PA_CATCH_PROGRAM_SYSTEM_EXCEPTIONS
8591
try{
@@ -94,18 +100,21 @@ void SingleSwitchProgramSession::run_program_instance(SingleSwitchProgramEnviron
94100
}
95101
#else
96102
{
97-
m_option.instance().program(env, scope);
98-
env.console.controller().wait_for_all(&scope);
103+
m_option.instance().program(env, context);
104+
context.wait_for_all_requests();
99105
}
100106
#endif
107+
108+
std::lock_guard<std::mutex> lg(program_lock());
101109
m_scope.store(nullptr, std::memory_order_release);
102110
}
103111
void SingleSwitchProgramSession::internal_stop_program(){
104-
WriteSpinLock lg(m_lock);
105-
106-
CancellableScope* scope = m_scope.load(std::memory_order_acquire);
107-
if (scope != nullptr){
108-
scope->cancel(std::make_exception_ptr(ProgramCancelledException()));
112+
{
113+
std::lock_guard<std::mutex> lg(program_lock());
114+
CancellableScope* scope = m_scope.load(std::memory_order_acquire);
115+
if (scope != nullptr){
116+
scope->cancel(std::make_exception_ptr(ProgramCancelledException()));
117+
}
109118
}
110119

111120
// Wait for program thread to finish.

SerialPrograms/Source/NintendoSwitch/Framework/NintendoSwitch_SingleSwitchProgramSession.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
#ifndef PokemonAutomation_NintendoSwitch_SingleSwitchProgramSession_H
1616
#define PokemonAutomation_NintendoSwitch_SingleSwitchProgramSession_H
1717

18-
#include "Common/Cpp/Concurrency/SpinLock.h"
1918
#include "CommonFramework/ProgramSession.h"
2019
#include "NintendoSwitch_SwitchSystemSession.h"
2120
#include "NintendoSwitch/NintendoSwitch_SingleSwitchProgram.h"
@@ -50,7 +49,6 @@ class SingleSwitchProgramSession final : public ProgramSession{
5049
SingleSwitchProgramOption& m_option;
5150
SwitchSystemSession m_system;
5251

53-
SpinLock m_lock;
5452
std::atomic<CancellableScope*> m_scope;
5553
};
5654

0 commit comments

Comments
 (0)