Code enhancement: Prevent backup worker thread crash at Notepad++ exit

Use thread safe g_bNppExitFlag and optimize the Notepad_plus::backupDocument worker thread.

Fix: https://github.com/notepad-plus-plus/notepad-plus-plus/pull/15681#issuecomment-2403168094, close #15935
This commit is contained in:
xomx 2024-12-10 16:49:31 +01:00 committed by Don Ho
parent fdf3ed2714
commit dc583bf34e
4 changed files with 19 additions and 9 deletions

View File

@ -8653,23 +8653,22 @@ void Notepad_plus::launchDocumentBackupTask()
DWORD WINAPI Notepad_plus::backupDocument(void * /*param*/) DWORD WINAPI Notepad_plus::backupDocument(void * /*param*/)
{ {
bool isSnapshotMode = true; NppGUI& nppGUI = (NppParameters::getInstance()).getNppGUI();
while (isSnapshotMode)
{
NppParameters& nppParam = NppParameters::getInstance();
size_t timer = nppParam.getNppGUI()._snapshotBackupTiming; while (!g_bNppExitFlag.load() && nppGUI.isSnapshotMode())
{
size_t timer = nppGUI._snapshotBackupTiming;
if (timer < 1000) if (timer < 1000)
timer = 1000; timer = 1000;
::Sleep(DWORD(timer)); ::Sleep(DWORD(timer));
isSnapshotMode = nppParam.getNppGUI().isSnapshotMode(); if (g_bNppExitFlag.load() || !nppGUI.isSnapshotMode())
if (!isSnapshotMode)
break; break;
::SendMessage(Notepad_plus_Window::gNppHWND, NPPM_INTERNAL_SAVEBACKUP, 0, 0); ::SendMessage(Notepad_plus_Window::gNppHWND, NPPM_INTERNAL_SAVEBACKUP, 0, 0);
} }
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }

View File

@ -46,10 +46,13 @@
#include <vector> #include <vector>
#include <iso646.h> #include <iso646.h>
#include <chrono> #include <chrono>
#include <atomic>
extern std::chrono::steady_clock::time_point g_nppStartTimePoint; extern std::chrono::steady_clock::time_point g_nppStartTimePoint;
extern std::chrono::steady_clock::duration g_pluginsLoadingTime; extern std::chrono::steady_clock::duration g_pluginsLoadingTime;
extern std::atomic<bool> g_bNppExitFlag;
#define MENU 0x01 #define MENU 0x01
#define TOOLBAR 0x02 #define TOOLBAR 0x02

View File

@ -20,6 +20,7 @@
#include <uxtheme.h> // for EnableThemeDialogTexture #include <uxtheme.h> // for EnableThemeDialogTexture
#include <format> #include <format>
#include <windowsx.h> // for GET_X_LPARAM, GET_Y_LPARAM #include <windowsx.h> // for GET_X_LPARAM, GET_Y_LPARAM
#include <atomic>
#include "Notepad_plus_Window.h" #include "Notepad_plus_Window.h"
#include "TaskListDlg.h" #include "TaskListDlg.h"
#include "ImageListSet.h" #include "ImageListSet.h"
@ -39,6 +40,8 @@ using namespace std;
#define WM_DPICHANGED 0x02E0 #define WM_DPICHANGED 0x02E0
#endif #endif
std::atomic<bool> g_bNppExitFlag{ false };
struct SortTaskListPred final struct SortTaskListPred final
{ {
@ -2721,6 +2724,11 @@ LRESULT Notepad_plus::process(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa
return 0; // abort quitting return 0; // abort quitting
} }
// from this point on the Notepad++ exit is inevitable
g_bNppExitFlag.store(true); // thread-safe op
// currently it is used only in the Notepad_plus::backupDocument worker thread,
// use it in such a thread like: if (g_bNppExitFlag.load()) -> finish work of & exit the thread
if (_beforeSpecialView._isFullScreen) //closing, return to windowed mode if (_beforeSpecialView._isFullScreen) //closing, return to windowed mode
fullScreenToggle(); fullScreenToggle();
if (_beforeSpecialView._isPostIt) //closing, return to windowed mode if (_beforeSpecialView._isPostIt) //closing, return to windowed mode

View File

@ -1086,7 +1086,7 @@ bool FileManager::backupCurrentBuffer()
{ {
size_t lengthDoc = _pNotepadPlus->_pEditView->getCurrentDocLen(); size_t lengthDoc = _pNotepadPlus->_pEditView->getCurrentDocLen();
char* buf = (char*)_pNotepadPlus->_pEditView->execute(SCI_GETCHARACTERPOINTER); //to get characters directly from Scintilla buffer char* buf = (char*)_pNotepadPlus->_pEditView->execute(SCI_GETCHARACTERPOINTER); //to get characters directly from Scintilla buffer
boolean isWrittenSuccessful = false; bool isWrittenSuccessful = false;
if (encoding == -1) //no special encoding; can be handled directly by Utf8_16_Write if (encoding == -1) //no special encoding; can be handled directly by Utf8_16_Write
{ {
@ -1248,7 +1248,7 @@ SavingStatus FileManager::saveBuffer(BufferID id, const wchar_t* filename, bool
size_t lengthDoc = _pscratchTilla->getCurrentDocLen(); size_t lengthDoc = _pscratchTilla->getCurrentDocLen();
char* buf = (char*)_pscratchTilla->execute(SCI_GETCHARACTERPOINTER); //to get characters directly from Scintilla buffer char* buf = (char*)_pscratchTilla->execute(SCI_GETCHARACTERPOINTER); //to get characters directly from Scintilla buffer
boolean isWrittenSuccessful = false; bool isWrittenSuccessful = false;
if (encoding == -1) //no special encoding; can be handled directly by Utf8_16_Write if (encoding == -1) //no special encoding; can be handled directly by Utf8_16_Write
{ {