[BUG_FIXED] Fix windows 7 crash bug while executing update.

[BUG_FIXED] (Author: Christian Cuvier) Fix find performance issue related macro recording.


git-svn-id: svn://svn.tuxfamily.org/svnroot/notepadplus/repository/trunk@675 f5eea248-9336-0410-98b8-ebc06183d4e3
remotes/trunk
Don Ho 2010-10-03 23:38:11 +00:00
parent 9ab9b02e6a
commit e420ae3707
7 changed files with 45 additions and 366 deletions

View File

@ -16,280 +16,16 @@
//Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#include "precompiledHeaders.h"
#include "Parameters.h"
#include "process.h"
BOOL Process::run()
void Process::run()
{
BOOL result = TRUE;
// stdout & stderr pipes for process to write
HANDLE hPipeOutW = NULL;
HANDLE hPipeErrW = NULL;
HANDLE hListenerStdOutThread = NULL;
HANDLE hListenerStdErrThread = NULL;
HANDLE hWaitForProcessEndThread = NULL;
HANDLE hListenerEvent[2];
hListenerEvent[0] = NULL;
hListenerEvent[1] = NULL;
SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE }; // inheritable handle
try {
// Create stdout pipe
if (!::CreatePipe(&_hPipeOutR, &hPipeOutW, &sa, 0))
throw std::runtime_error("Create stdout pipe failed");
// Create stderr pipe
if (!::CreatePipe(&_hPipeErrR, &hPipeErrW, &sa, 0))
throw std::runtime_error("Create stderr pipe failed");
STARTUPINFO startup;
PROCESS_INFORMATION procinfo;
::ZeroMemory(&startup, sizeof(startup));
startup.cb = sizeof(startup);
startup.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
startup.wShowWindow = (_type == WIN32_PROG)?SW_SHOW:SW_HIDE; // hidden console window
startup.hStdInput = NULL; // not used
startup.hStdOutput = hPipeOutW;
startup.hStdError = hPipeErrW;
generic_string cmd = TEXT("\"");
cmd += _command;
cmd += TEXT("\"");
if (_args[0])
{
cmd += TEXT(" ");
cmd += _args;
}
BOOL started = ::CreateProcess(NULL, // command is part of input generic_string
(TCHAR *)cmd.c_str(), // (writeable) command generic_string
NULL, // process security
NULL, // thread security
TRUE, // inherit handles flag
(_type == WIN32_PROG)?NULL:CREATE_SUSPENDED, // flags
NULL, // inherit environment
_curDir.c_str(), // inherit directory
&startup, // STARTUPINFO
&procinfo); // PROCESS_INFORMATION
_hProcess = procinfo.hProcess;
_hProcessThread = procinfo.hThread;
if(!started)
throw std::runtime_error("CreateProcess function call failed");
if (_type == CONSOLE_PROG)
{
hListenerEvent[0] = ::CreateEvent(NULL, FALSE, FALSE, TEXT("listenerEvent"));
if(!hListenerEvent[0])
throw std::runtime_error("Create listenerEvent failed");
hListenerEvent[1] = ::CreateEvent(NULL, FALSE, FALSE, TEXT("listenerStdErrEvent"));
if(!hListenerEvent[1])
throw std::runtime_error("Create listenerStdErrEvent failed");
// The process is running so we set this to FALSE
_bProcessEnd = FALSE;
hWaitForProcessEndThread = ::CreateThread(NULL, 0, staticWaitForProcessEnd, this, 0, NULL);
if (!hWaitForProcessEndThread)
throw std::runtime_error("CreateThread for staticWaitForProcessEnd failed");
hListenerStdOutThread = ::CreateThread(NULL, 0, staticListenerStdOut, this, 0, NULL);
if (!hListenerStdOutThread)
throw std::runtime_error("CreateThread for staticListenerStdOut failed");
hListenerStdErrThread = ::CreateThread(NULL, 0, staticListenerStdErr, this, 0, NULL);
if (!hListenerStdErrThread)
throw std::runtime_error("CreateThread for staticListenerStdErr failed");
// We wait until the process is over
// TO DO: This should be a bit secured in case something happen and the
// _bProcessEnd variable never gets set to TRUE... (by checking process
// state as well for instance to see if it is still running...)
while (!_bProcessEnd)
{
MSG msg;
while( ::PeekMessage( &msg, NULL, 0, 0, PM_REMOVE))
{
if( msg.message == WM_QUIT)
{
::PostQuitMessage(0);
// We do not exit but simply break in order to close
// handles properly
_bProcessEnd = TRUE;
break;
}
else
{
::TranslateMessage( &msg);
::DispatchMessage( &msg);
}
}
}
}
} catch (int coderr){
TCHAR str[10];
wsprintf(str, TEXT("%d"), coderr);
::MessageBox(NULL, str, TEXT("Exception :"), MB_OK);
}
// on va fermer toutes les handles
if (hPipeOutW)
::CloseHandle(hPipeOutW);
if (hPipeErrW)
::CloseHandle(hPipeErrW);
if (_hPipeOutR)
::CloseHandle(_hPipeOutR);
if (_hPipeErrR)
::CloseHandle(_hPipeErrR);
if (hListenerStdOutThread)
::CloseHandle(hListenerStdOutThread);
if (hListenerStdErrThread)
::CloseHandle(hListenerStdErrThread);
if (hWaitForProcessEndThread)
::CloseHandle(hWaitForProcessEndThread);
if (hListenerEvent[0])
::CloseHandle(hListenerEvent[0]);
if (hListenerEvent[1])
::CloseHandle(hListenerEvent[1]);
return result;
TCHAR *opVerb = TEXT("open");
winVer winVersion = (NppParameters::getInstance())->getWinVersion();
if (winVersion == WV_VISTA || winVersion == WV_WIN7)
opVerb = TEXT("runas");
::ShellExecute(NULL, opVerb, _command.c_str(), _args.c_str(), _curDir.c_str(), SW_SHOWNORMAL);
}
#define MAX_LINE_LENGTH 1024
void Process::listenerStdOut()
{
//BOOL Result = 0;
//DWORD size = 0;
DWORD bytesAvail = 0;
BOOL result = 0;
HANDLE hListenerEvent = ::OpenEvent(EVENT_ALL_ACCESS, FALSE, TEXT("listenerEvent"));
//FILE *fp = NULL;
int taille = 0;
TCHAR bufferOut[MAX_LINE_LENGTH + 1];
//TCHAR bufferErr[MAX_LINE_LENGTH + 1];
int nExitCode = STILL_ACTIVE;
DWORD outbytesRead;
::ResumeThread(_hProcessThread);
for(;;)
{ // got data
memset(bufferOut,0x00,MAX_LINE_LENGTH + 1);
//memset(bufferErr,0x00,MAX_LINE_LENGTH + 1);
taille = sizeof(bufferOut) - sizeof(TCHAR);
Sleep(50);
if (!::PeekNamedPipe(_hPipeOutR, bufferOut, taille, &outbytesRead, &bytesAvail, NULL))
{
bytesAvail = 0;
break;
}
if(outbytesRead)
{
result = :: ReadFile(_hPipeOutR, bufferOut, taille, &outbytesRead, NULL);
if ((!result) && (outbytesRead == 0))
break;
}
//outbytesRead = lstrlen(bufferOut);
bufferOut[outbytesRead] = '\0';
generic_string s;
s.assign(bufferOut);
_stdoutStr += s;
if (::GetExitCodeProcess(_hProcess, (unsigned long*)&nExitCode))
{
if (nExitCode != STILL_ACTIVE)
break; // EOF condition
}
//else
//break;
}
_exitCode = nExitCode;
if(!::SetEvent(hListenerEvent))
{
::MessageBox(NULL, TEXT("SetEvent function call failed"), TEXT("Thread listenerStdOut"), MB_OK);
}
}
void Process::listenerStdErr()
{
//BOOL Result = 0;
//DWORD size = 0;
DWORD bytesAvail = 0;
BOOL result = 0;
HANDLE hListenerEvent = ::OpenEvent(EVENT_ALL_ACCESS, FALSE, TEXT("listenerStdErrEvent"));
int taille = 0;
//TCHAR bufferOut[MAX_LINE_LENGTH + 1];
TCHAR bufferErr[MAX_LINE_LENGTH + 1];
int nExitCode = STILL_ACTIVE;
DWORD errbytesRead;
::ResumeThread(_hProcessThread);
for(;;)
{ // got data
memset(bufferErr, 0x00, MAX_LINE_LENGTH + 1);
taille = sizeof(bufferErr) - sizeof(TCHAR);
Sleep(50);
if (!::PeekNamedPipe(_hPipeErrR, bufferErr, taille, &errbytesRead, &bytesAvail, NULL))
{
bytesAvail = 0;
break;
}
if(errbytesRead)
{
result = :: ReadFile(_hPipeErrR, bufferErr, taille, &errbytesRead, NULL);
if ((!result) && (errbytesRead == 0))
break;
}
//outbytesRead = lstrlen(bufferOut);
bufferErr[errbytesRead] = '\0';
generic_string s;
s.assign(bufferErr);
_stderrStr += s;
if (::GetExitCodeProcess(_hProcess, (unsigned long*)&nExitCode))
{
if (nExitCode != STILL_ACTIVE)
break; // EOF condition
}
}
if(!::SetEvent(hListenerEvent))
{
::MessageBox(NULL, TEXT("SetEvent function call failed"), TEXT("Thread stdout listener"), MB_OK);
}
}
void Process::waitForProcessEnd()
{
HANDLE hListenerEvent[2];
hListenerEvent[0] = ::OpenEvent(EVENT_ALL_ACCESS, FALSE, TEXT("listenerEvent"));
hListenerEvent[1] = ::OpenEvent(EVENT_ALL_ACCESS, FALSE, TEXT("listenerStdErrEvent"));
::WaitForSingleObject(_hProcess, INFINITE);
::WaitForMultipleObjects(2, hListenerEvent, TRUE, INFINITE);
_bProcessEnd = TRUE;
}

View File

@ -25,76 +25,15 @@ enum progType {WIN32_PROG, CONSOLE_PROG};
class Process
{
public:
Process(progType pt = WIN32_PROG) : _type(pt) {};
Process(const TCHAR *cmd, const TCHAR *args, const TCHAR *cDir, progType pt = WIN32_PROG)
: _type(pt), _stdoutStr(TEXT("")), _stderrStr(TEXT("")), _hPipeOutR(NULL),
_hPipeErrR(NULL), _hProcess(NULL), _hProcessThread(NULL),
_command(cmd), _args(args), _curDir(cDir), _bProcessEnd(TRUE)
{};
Process(const TCHAR *cmd, const TCHAR *args, const TCHAR *cDir)
:_command(cmd), _args(args), _curDir(cDir){};
BOOL run();
const TCHAR * getStdout() const {
return _stdoutStr.c_str();
};
const TCHAR * getStderr() const {
return _stderrStr.c_str();
};
int getExitCode() const {
return _exitCode;
};
bool hasStdout() {
return (_stdoutStr.compare(TEXT("")) != 0);
};
bool hasStderr() {
return (_stderrStr.compare(TEXT("")) != 0);
};
void run();
protected:
progType _type;
// LES ENTREES
generic_string _command;
generic_string _args;
generic_string _curDir;
// LES SORTIES
generic_string _stdoutStr;
generic_string _stderrStr;
int _exitCode;
// LES HANDLES
HANDLE _hPipeOutR;
HANDLE _hPipeErrR;
HANDLE _hProcess;
HANDLE _hProcessThread;
BOOL _bProcessEnd;
//UINT _pid; // process ID assigned by caller
static DWORD WINAPI staticListenerStdOut(void * myself){
((Process *)myself)->listenerStdOut();
return 0;
};
static DWORD WINAPI staticListenerStdErr(void * myself) {
((Process *)myself)->listenerStdErr();
return 0;
};
static DWORD WINAPI staticWaitForProcessEnd(void * myself) {
((Process *)myself)->waitForProcessEnd();
return 0;
};
void listenerStdOut();
void listenerStdErr();
void waitForProcessEnd();
void error(const TCHAR *txt2display, BOOL & returnCode, int errCode);
};
#endif //PROCESSUS_H

View File

@ -939,11 +939,11 @@ LRESULT Notepad_plus::process(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lPa
return (_macro.empty())?0:MACRO_RECORDING_HAS_STOPPED;
case WM_FRSAVE_INT:
_macro.push_back(recordedMacroStep(wParam, 0, lParam, NULL));
_macro.push_back(recordedMacroStep(wParam, 0, lParam, NULL, recordedMacroStep::mtSavedSnR));
break;
case WM_FRSAVE_STR:
_macro.push_back(recordedMacroStep(wParam, 0, 0, (const TCHAR *)lParam));
_macro.push_back(recordedMacroStep(wParam, 0, 0, (const TCHAR *)lParam, recordedMacroStep::mtSavedSnR));
break;
case WM_MACRODLGRUNMACRO:

View File

@ -1757,6 +1757,7 @@ void Notepad_plus::command(int id)
generic_string param = TEXT("-verbose -v");
param += VERSION_VALUE;
Process updater(updaterFullPath.c_str(), param.c_str(), updaterDir.c_str());
updater.run();
break;
}

View File

@ -1286,9 +1286,12 @@ bool FindReplaceDlg::processFindNext(const TCHAR *txt2find, const FindOption *op
int start = posFind;//int((*_ppEditView)->execute(SCI_GETTARGETSTART));
int end = int((*_ppEditView)->execute(SCI_GETTARGETEND));
// to make sure the found result is visible
// to make sure the found result is visible:
// prevent recording of absolute positioning commands issued in the process
(*_ppEditView)->execute(SCI_STOPRECORD);
Searching::displaySectionCentered(start, end, *_ppEditView, pOptions->_whichDirection == DIR_DOWN);
if (::SendMessage(_hParent, WM_GETCURRENTMACROSTATUS,0,0) == MACRO_RECORDING_IN_PROGRESS)
(*_ppEditView)->execute(SCI_STARTRECORD);
delete [] pText;
return true;

View File

@ -101,40 +101,40 @@ IDD_PREFERENCE_SETTING_BOX DIALOGEX 0, 0, 455, 185
STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD
FONT 8, "MS Shell Dlg", 0, 0, 0x1
BEGIN
GROUPBOX "Recent Files History",IDC_HISTORY_GB_STATIC,54,4,155,39,BS_CENTER
RTEXT "Max. number of entries :",IDC_MAXNBFILE_STATIC,57,14,112,8
GROUPBOX "Recent Files History",IDC_HISTORY_GB_STATIC,37,4,155,39,BS_CENTER
RTEXT "Max. number of entries :",IDC_MAXNBFILE_STATIC,40,14,112,8
LTEXT "0",IDC_MAXNBFILEVAL_STATIC,176,14,15,8
CONTROL "Don't check at launch time",IDC_CHECK_DONTCHECKHISTORY,
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,62,27,140,10
GROUPBOX "Document Switcher (Ctrl+TAB)",IDC_DOCUMENTSWITCHER_STATIC,54,48,155,39,BS_CENTER
CONTROL "Enable",IDC_CHECK_ENABLEDOCSWITCHER,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,62,59,69,10
CONTROL "Enable MRU behaviour",IDC_CHECK_STYLEMRU,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,62,72,140,10
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,45,27,140,10
GROUPBOX "Document Switcher (Ctrl+TAB)",IDC_DOCUMENTSWITCHER_STATIC,37,48,155,39,BS_CENTER
CONTROL "Enable",IDC_CHECK_ENABLEDOCSWITCHER,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,45,59,69,10
CONTROL "Enable MRU behaviour",IDC_CHECK_STYLEMRU,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,45,72,140,10
CONTROL "Enable Notepad++ auto-updater",IDC_CHECK_AUTOUPDATE,
"Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,55,94,150,10
CONTROL "Smart highlighting",IDC_CHECK_ENABLSMARTHILITE,"Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,55,136,150,10
CONTROL "Auto-indent",IDC_CHECK_MAINTAININDENT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,55,108,150,10
CONTROL "Minimize to system tray",IDC_CHECK_MIN2SYSTRAY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,55,122,150,10
"Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,37,94,150,10
CONTROL "Smart highlighting",IDC_CHECK_ENABLSMARTHILITE,"Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,37,136,150,10
CONTROL "Auto-indent",IDC_CHECK_MAINTAININDENT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,37,108,150,10
CONTROL "Minimize to system tray",IDC_CHECK_MIN2SYSTRAY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,37,122,150,10
CONTROL "Show only filename in title bar",IDC_CHECK_SHORTTITLE,
"Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,55,150,217,10
"Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,37,150,217,10
CONTROL "Remember current session for next launch",IDC_CHECK_REMEMBERSESSION,
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,55,164,217,10
GROUPBOX "Clickable Link Settings",IDC_CLICKABLELINK_STATIC,232,4,155,39,BS_CENTER
CONTROL "Enable",IDC_CHECK_CLICKABLELINK_ENABLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,240,15,140,10
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,37,164,217,10
GROUPBOX "Clickable Link Settings",IDC_CLICKABLELINK_STATIC,259,4,155,39,BS_CENTER
CONTROL "Enable",IDC_CHECK_CLICKABLELINK_ENABLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,267,15,140,10
CONTROL "No underline",IDC_CHECK_CLICKABLELINK_NOUNDERLINE,
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,240,28,140,10
GROUPBOX "File Status Auto-Detection",IDC_FILEAUTODETECTION_STATIC,232,47,155,50,BS_CENTER
CONTROL "Enable",IDC_CHECK_FILEAUTODETECTION,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,240,57,140,10
CONTROL "Update silently",IDC_CHECK_UPDATESILENTLY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,240,69,140,10
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,267,28,140,10
GROUPBOX "File Status Auto-Detection",IDC_FILEAUTODETECTION_STATIC,259,47,155,50,BS_CENTER
CONTROL "Enable",IDC_CHECK_FILEAUTODETECTION,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,267,57,140,10
CONTROL "Update silently",IDC_CHECK_UPDATESILENTLY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,267,69,140,10
CONTROL "Scroll to the last line after update",IDC_CHECK_UPDATEGOTOEOF,
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,240,81,140,10
GROUPBOX "Highlight Matching Tags",IDC_TAGMATCHEDHILITE_STATIC,232,101,155,50,BS_CENTER
CONTROL "Enable",IDC_CHECK_ENABLTAGSMATCHHILITE,"Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,240,111,140,10
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,267,81,140,10
GROUPBOX "Highlight Matching Tags",IDC_TAGMATCHEDHILITE_STATIC,259,101,155,50,BS_CENTER
CONTROL "Enable",IDC_CHECK_ENABLTAGSMATCHHILITE,"Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,267,111,140,10
CONTROL "Highlight tag attributes",IDC_CHECK_ENABLTAGATTRHILITE,
"Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,240,123,140,10
"Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,267,123,140,10
CONTROL "Highlight comment/php/asp zone",IDC_CHECK_HIGHLITENONEHTMLZONE,
"Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,240,136,140,10
RTEXT "Session file ext.:",IDC_SESSIONFILEEXT_STATIC,244,160,108,8
EDITTEXT IDC_EDIT_SESSIONFILEEXT,354,157,34,14,ES_AUTOHSCROLL
"Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,267,136,140,10
RTEXT "Session file ext.:",IDC_SESSIONFILEEXT_STATIC,271,160,108,8
EDITTEXT IDC_EDIT_SESSIONFILEEXT,381,157,34,14,ES_AUTOHSCROLL
END
IDD_PREFERENCE_NEWDOCSETTING_BOX DIALOGEX 0, 0, 455, 185

View File

@ -271,7 +271,7 @@ struct recordedMacroStep {
recordedMacroStep(int iMessage, long wParam, long lParam);
recordedMacroStep(int iCommandID) : message(0), wParameter(iCommandID), lParameter(0), MacroType(mtMenuCommand) {};
recordedMacroStep(int iMessage, long wParam, long lParam, const TCHAR *sParam, int type = mtSavedSnR)
recordedMacroStep(int iMessage, long wParam, long lParam, const TCHAR *sParam, int type)
: message(iMessage), wParameter(wParam), lParameter(lParam), MacroType(MacroTypeIndex(type)){
sParameter = (sParam)?generic_string(sParam):TEXT("");
};