Skip to content

Commit 9f50e1d

Browse files
committed
fix #547: Always stop threads owned by clones
Closes #547
1 parent b691e30 commit 9f50e1d

File tree

3 files changed

+40
-3
lines changed

3 files changed

+40
-3
lines changed

src/engine/internal/engine.cpp

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -366,15 +366,33 @@ void Engine::start()
366366
void Engine::stop()
367367
{
368368
// https://github.com/scratchfoundation/scratch-vm/blob/f1aa92fad79af17d9dd1c41eeeadca099339a9f1/src/engine/runtime.js#L2057-L2081
369-
deleteClones();
370-
stopSounds();
371-
372369
if (m_activeThread) {
373370
stopThread(m_activeThread.get());
374371
// NOTE: The project should continue running even after "stop all" is called and the remaining threads should be stepped once.
375372
// The remaining threads can even start new threads which will ignore the "stop all" call and will "restart" the project.
376373
// This is probably a bug in the Scratch VM, but let's keep it here to keep it compatible.
377374
m_threadsToStop = m_threads;
375+
376+
// Remove threads owned by clones because clones are going to be deleted (#547)
377+
m_threads.erase(
378+
std::remove_if(
379+
m_threads.begin(),
380+
m_threads.end(),
381+
[](std::shared_ptr<VirtualMachine> thread) {
382+
assert(thread);
383+
Target *target = thread->target();
384+
assert(target);
385+
386+
if (!target->isStage()) {
387+
Sprite *sprite = static_cast<Sprite *>(target);
388+
389+
if (sprite->isClone())
390+
return true;
391+
}
392+
393+
return false;
394+
}),
395+
m_threads.end());
378396
} else {
379397
// If there isn't any active thread, it means the project was stopped from the outside
380398
// In this case all threads should be removed and the project should be considered stopped
@@ -387,6 +405,8 @@ void Engine::stop()
387405
m_running = false;
388406
}
389407

408+
deleteClones();
409+
stopSounds();
390410
m_stopped();
391411
}
392412

test/engine/engine_test.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2303,3 +2303,20 @@ TEST(EngineTest, NoCrashWithUndefinedVariableOrList)
23032303
ASSERT_EQ(list->id(), "}l+w#Er5y!:*gh~5!3t%");
23042304
ASSERT_TRUE(list->empty());
23052305
}
2306+
2307+
TEST(EngineTest, AlwaysStopCloneThreads)
2308+
{
2309+
// Regtest for #547
2310+
Project p("regtest_projects/547_stop_clone_threads_in_stop_all.sb3");
2311+
ASSERT_TRUE(p.load());
2312+
2313+
auto engine = p.engine();
2314+
2315+
Stage *stage = engine->stage();
2316+
ASSERT_TRUE(stage);
2317+
2318+
engine->run();
2319+
2320+
ASSERT_VAR(stage, "test");
2321+
ASSERT_EQ(GET_VAR(stage, "test")->value().toInt(), 0);
2322+
}
1.72 KB
Binary file not shown.

0 commit comments

Comments
 (0)