Skip to content

Commit

Permalink
Fix opened network files hanging issue while the network disconnected
Browse files Browse the repository at this point in the history
The issue is due to WinAPI's GetFileAttributes function can take a huge amount of time in various situations, like when the target server being offline (usalally).
The current solution is to wait at least 3 seconds for each GetFileAttributes function, then return the default value in case of the problem (or the returned value of the function, in case of normal situation - if it has been executed completely during the 3 seconds).
So there'll still be the hanging time (3 or 6 seconds) while the problem of network connection, but the hanging time (it could be 30 seconds more) is reduced considerablly.

Fix notepad-plus-plus#4306, fix notepad-plus-plus#6178, fix notepad-plus-plus#8055, fix notepad-plus-plus#11388, fix notepad-plus-plus#12553, fix notepad-plus-plus#15540
  • Loading branch information
donho committed Sep 27, 2024
1 parent fc051a1 commit efc306a
Show file tree
Hide file tree
Showing 10 changed files with 61 additions and 23 deletions.
56 changes: 48 additions & 8 deletions PowerEditor/src/MISC/Common/Common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1213,7 +1213,7 @@ bool isCertificateValidated(const wstring & fullFilePath, const wstring & subjec

bool isAssoCommandExisting(LPCTSTR FullPathName)
{
bool isAssoCommandExisting = false;
bool isAssoCmdExist = false;

bool isFileExisting = doesFileExist(FullPathName);

Expand All @@ -1228,11 +1228,11 @@ bool isAssoCommandExisting(LPCTSTR FullPathName)
// check if association exist
hres = AssocQueryString(ASSOCF_VERIFY|ASSOCF_INIT_IGNOREUNKNOWN, ASSOCSTR_COMMAND, ext, NULL, buffer, &bufferLen);

isAssoCommandExisting = (hres == S_OK) // check if association exist and no error
&& (wcsstr(buffer, L"notepad++.exe")) == NULL; // check association with notepad++
isAssoCmdExist = (hres == S_OK) // check if association exist and no error
&& (wcsstr(buffer, L"notepad++.exe")) == NULL; // check association with notepad++

}
return isAssoCommandExisting;
return isAssoCmdExist;
}

std::wstring s2ws(const std::string& str)
Expand Down Expand Up @@ -1764,20 +1764,60 @@ bool Version::isCompatibleTo(const Version& from, const Version& to) const
return false;
}


/*
bool doesFileExist(const wchar_t* filePath)
{
DWORD dwAttrib = ::GetFileAttributesW(filePath);
return (dwAttrib != INVALID_FILE_ATTRIBUTES && !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
}
*/

struct GetAttrParamResult {
std::wstring _filePath;
DWORD _fileAttr;
};

DWORD WINAPI getFileAttributesWorker(void* data)
{
GetAttrParamResult* inAndOut = static_cast<GetAttrParamResult*>(data);
inAndOut->_fileAttr = ::GetFileAttributesW(inAndOut->_filePath.c_str());
return TRUE;
};

DWORD getFileAttrWaitFewSec(const wchar_t* filePath)
{
GetAttrParamResult data;
data._fileAttr = INVALID_FILE_ATTRIBUTES;
data._filePath = filePath;
HANDLE hThread = ::CreateThread(NULL, 0, getFileAttributesWorker, &data, 0, NULL);
if (!hThread)
{
return false;
}

// Wait for 3 sec
::WaitForSingleObject(hThread, 3000);
CloseHandle(hThread);

return data._fileAttr;
};

bool doesFileExist(const wchar_t* filePath)
{
DWORD attr = getFileAttrWaitFewSec(filePath);
return (attr != INVALID_FILE_ATTRIBUTES && !(attr & FILE_ATTRIBUTE_DIRECTORY));
}

bool doesDirectoryExist(const wchar_t* dirPath)
{
DWORD dwAttrib = ::GetFileAttributesW(dirPath);
return (dwAttrib != INVALID_FILE_ATTRIBUTES && (dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
DWORD attr = getFileAttrWaitFewSec(dirPath);
return (attr != INVALID_FILE_ATTRIBUTES && (attr & FILE_ATTRIBUTE_DIRECTORY));
}

bool doesPathExist(const wchar_t* path)
{
DWORD dwAttrib = ::GetFileAttributesW(path);
return (dwAttrib != INVALID_FILE_ATTRIBUTES);
DWORD attr = getFileAttrWaitFewSec(path);
return (attr != INVALID_FILE_ATTRIBUTES);
}

3 changes: 2 additions & 1 deletion PowerEditor/src/MISC/Common/Common.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@
#include <algorithm>
#include <tchar.h>

#pragma deprecated(PathFileExists) // Use doesFileExist, doesDirectoryExist or doesPathExist (for file or directory) instead.
#pragma deprecated(PathFileExists) // Use doesFileExist, doesDirectoryExist or doesPathExist (for file or directory) instead.
#pragma deprecated(PathIsDirectory) // Use doesDirectoryExist instead.


const bool dirUp = true;
Expand Down
6 changes: 3 additions & 3 deletions PowerEditor/src/Notepad_plus.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2613,7 +2613,7 @@ void Notepad_plus::checkDocState()
enableCommand(IDM_FILE_RELOAD, isFileExisting, MENU);
enableCommand(IDM_FILE_CONTAININGFOLDERASWORKSPACE, isFileExisting, MENU);

enableCommand(IDM_FILE_OPEN_DEFAULT_VIEWER, isAssoCommandExisting(curBuf->getFullPathName()), MENU);
enableCommand(IDM_FILE_OPEN_DEFAULT_VIEWER, isFileExisting ? isAssoCommandExisting(curBuf->getFullPathName()) : false, MENU);

enableCommand(IDM_VIEW_IN_FIREFOX, isFileExisting, MENU);
enableCommand(IDM_VIEW_IN_CHROME, isFileExisting, MENU);
Expand Down Expand Up @@ -4435,7 +4435,7 @@ void Notepad_plus::dropFiles(HDROP hdrop)
{
wchar_t pathDropped[MAX_PATH];
::DragQueryFile(hdrop, i, pathDropped, MAX_PATH);
if (::PathIsDirectory(pathDropped))
if (doesDirectoryExist(pathDropped))
{
size_t len = lstrlen(pathDropped);
if (len > 0 && pathDropped[len - 1] != wchar_t('\\'))
Expand Down Expand Up @@ -7040,7 +7040,7 @@ void Notepad_plus::setWorkingDir(const wchar_t *dir)
{
params.setWorkingDir(NULL);
}
else if (dir && PathIsDirectory(dir))
else if (dir && doesDirectoryExist(dir))
{
params.setWorkingDir(dir);
}
Expand Down
2 changes: 1 addition & 1 deletion PowerEditor/src/NppCommands.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -595,7 +595,7 @@ void Notepad_plus::command(int id)
fullFilePath += L"\"";

if (id == IDM_EDIT_OPENINFOLDER ||
(id == IDM_EDIT_OPENASFILE && !::PathIsDirectory(curentWord)))
(id == IDM_EDIT_OPENASFILE && !doesDirectoryExist(curentWord)))
::ShellExecute(hwnd, L"open", cmd2Exec, fullFilePath.c_str(), L".", SW_SHOW);
}
else // Relative file path - need concatenate with current full file path
Expand Down
2 changes: 1 addition & 1 deletion PowerEditor/src/NppIO.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -477,7 +477,7 @@ BufferID Notepad_plus::doOpen(const wstring& fileName, bool isRecursive, bool is
}
else
{
if (globbing || ::PathIsDirectory(targetFileName.c_str()))
if (globbing || doesDirectoryExist(targetFileName.c_str()))
{
vector<wstring> fileNames;
vector<wstring> patterns;
Expand Down
2 changes: 1 addition & 1 deletion PowerEditor/src/Parameters.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1244,7 +1244,7 @@ bool NppParameters::load()
//
if (!_cmdSettingsDir.empty())
{
if (!::PathIsDirectory(_cmdSettingsDir.c_str()))
if (!doesDirectoryExist(_cmdSettingsDir.c_str()))
{
// The following text is not translatable.
// _pNativeLangSpeaker is initialized AFTER _userPath being dterminated because nativeLang.xml is from from _userPath.
Expand Down
2 changes: 0 additions & 2 deletions PowerEditor/src/ScintillaComponent/Buffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -420,8 +420,6 @@ wstring Buffer::getTimeString(FILETIME rawtime) const

wstring Buffer::getFileTime(fileTimeType ftt) const
{
wstring filePath;

WIN32_FILE_ATTRIBUTE_DATA attributes{};
if (GetFileAttributesEx(_currentStatus == DOC_UNNAMED ? _backupFileName.c_str() : _fullPathName.c_str(), GetFileExInfoStandard, &attributes) != 0)
{
Expand Down
2 changes: 1 addition & 1 deletion PowerEditor/src/ScintillaComponent/FindReplaceDlg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2648,7 +2648,7 @@ intptr_t CALLBACK FindReplaceDlg::run_dlgProc(UINT message, WPARAM wParam, LPARA
currPath = buf->getFullPathName();
PathRemoveFileSpec(currPath);
}
if (currPath.empty() || !PathIsDirectory(currPath.c_str()))
if (currPath.empty() || !doesDirectoryExist(currPath.c_str()))
currPath = NppParameters::getInstance().getWorkingDir();
::SetDlgItemText(_hSelf, IDD_FINDINFILES_DIR_COMBO, currPath.c_str());
}
Expand Down
4 changes: 2 additions & 2 deletions PowerEditor/src/WinControls/FileBrowser/fileBrowser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1235,7 +1235,7 @@ bool FileBrowser::addToTree(FilesToChange & group, HTREEITEM node)

// Not found, good - Action
for (auto & file : group._files) {
if (::PathIsDirectory((group._commonPath + file).c_str()))
if (doesDirectoryExist((group._commonPath + file).c_str()))
{
SortingData4lParam* customData = new SortingData4lParam(L"", file, true);
sortingDataArray.push_back(customData);
Expand Down Expand Up @@ -1468,7 +1468,7 @@ bool FolderInfo::addToStructure(wstring & fullpath, std::vector<wstring> linarPa
{
fullpath += L"\\";
fullpath += linarPathArray[0];
if (PathIsDirectory(fullpath.c_str()))
if (doesDirectoryExist(fullpath.c_str()))
{
// search in folders, if found - no good
for (const auto& folder : _subFolders)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@


#include <shobjidl.h>
#include <shlwapi.h> // PathIsDirectory
#ifdef __MINGW32__
#include <cwchar>
#endif
Expand Down Expand Up @@ -142,7 +141,7 @@ namespace // anonymous
HRESULT hr = SHCreateItemFromParsingName(path,
nullptr,
IID_PPV_ARGS(&shellItem));
if (SUCCEEDED(hr) && shellItem && !::PathIsDirectory(path))
if (SUCCEEDED(hr) && shellItem && !::doesDirectoryExist(path))
{
com_ptr<IShellItem> parentItem;
hr = shellItem->GetParent(&parentItem);
Expand Down Expand Up @@ -506,7 +505,7 @@ class FileDialogEventHandler final : public IFileDialogEvents, public IFileDialo
expandEnv(fileName);
bool nameChanged = transformPath(fileName);
// Update the controls.
if (!::PathIsDirectory(getAbsPath(fileName).c_str()))
if (doesDirectoryExist(getAbsPath(fileName).c_str()))
{
// Name is a file path.
// Add file extension if missing.
Expand Down

0 comments on commit efc306a

Please sign in to comment.