h_mgr: fix: ModuleInitState wasn't set => shutdown didn't happen => leaked a lot of memory
sysdep/win: save-last-error logic now wrapped in a scoped class (avoids need for "goto exit") This was SVN commit r5527.
This commit is contained in:
parent
5bf9bca9ef
commit
2bffecb331
@ -793,6 +793,8 @@ static ModuleInitState initState;
|
||||
|
||||
void h_mgr_init()
|
||||
{
|
||||
if(!ModuleShouldInitialize(&initState))
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
@ -194,8 +194,9 @@ static void get_packet();
|
||||
// better to use a cached string from rel_chdir - secure
|
||||
LibError dir_add_watch(const char* dir, intptr_t* preqnum)
|
||||
{
|
||||
WinScopedPreserveLastError s; // Create*
|
||||
|
||||
LibError err = ERR::FAIL;
|
||||
WIN_SAVE_LAST_ERROR; // Create*
|
||||
|
||||
intptr_t reqnum;
|
||||
*preqnum = 0;
|
||||
@ -214,9 +215,9 @@ LibError dir_add_watch(const char* dir, intptr_t* preqnum)
|
||||
const char* old_dir = w->dir_name.c_str();
|
||||
if(path_is_subpath(dir, old_dir))
|
||||
{
|
||||
reqnum = w->reqnum;
|
||||
*preqnum = w->reqnum;
|
||||
w->refs++;
|
||||
goto done;
|
||||
return INFO::OK;
|
||||
}
|
||||
}
|
||||
|
||||
@ -225,7 +226,7 @@ LibError dir_add_watch(const char* dir, intptr_t* preqnum)
|
||||
const DWORD flags = FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED;
|
||||
const HANDLE hDir = CreateFile(dir, FILE_LIST_DIRECTORY, share, 0, OPEN_EXISTING, flags, 0);
|
||||
if(hDir == INVALID_HANDLE_VALUE)
|
||||
goto fail;
|
||||
WARN_RETURN(ERR::FAIL);
|
||||
|
||||
// assign a new (unique) request number. don't do this earlier - prevents
|
||||
// DOS via wasting reqnums due to invalid directory parameters.
|
||||
@ -234,7 +235,7 @@ LibError dir_add_watch(const char* dir, intptr_t* preqnum)
|
||||
{
|
||||
debug_assert(0); // request numbers are no longer unique
|
||||
CloseHandle(hDir);
|
||||
goto fail;
|
||||
WARN_RETURN(ERR::LIMIT);
|
||||
}
|
||||
reqnum = ++last_reqnum;
|
||||
|
||||
@ -247,24 +248,17 @@ LibError dir_add_watch(const char* dir, intptr_t* preqnum)
|
||||
if(hIOCP == 0 || hIOCP == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
CloseHandle(hDir);
|
||||
goto fail;
|
||||
WARN_RETURN(ERR::FAIL);
|
||||
}
|
||||
|
||||
// allocate watch, add to list, associate with reqnum
|
||||
// note: can't use SAFE_NEW due to ctor params.
|
||||
try
|
||||
{
|
||||
Watch* w = new Watch(reqnum, dir_s, hDir);
|
||||
(*watches)[reqnum] = w;
|
||||
Watch* w = new Watch(reqnum, dir_s, hDir);
|
||||
(*watches)[reqnum] = w;
|
||||
|
||||
// add trailing \ if not already there
|
||||
if(dir_s[dir_s.length()-1] != '\\')
|
||||
w->dir_name += '\\';
|
||||
}
|
||||
catch(std::bad_alloc)
|
||||
{
|
||||
goto fail;
|
||||
}
|
||||
// add trailing \ if not already there
|
||||
if(dir_s[dir_s.length()-1] != '\\')
|
||||
w->dir_name += '\\';
|
||||
|
||||
|
||||
// post a dummy kickoff packet; the IOCP polling code will "re"issue
|
||||
@ -277,13 +271,8 @@ LibError dir_add_watch(const char* dir, intptr_t* preqnum)
|
||||
get_packet();
|
||||
}
|
||||
|
||||
done:
|
||||
err = INFO::OK;
|
||||
*preqnum = reqnum;
|
||||
|
||||
fail:
|
||||
WIN_RESTORE_LAST_ERROR;
|
||||
return err;
|
||||
return INFO::OK;
|
||||
}
|
||||
|
||||
|
||||
|
@ -28,7 +28,7 @@
|
||||
|
||||
static LibError ReadVersionString(const OsPath& modulePathname_, char* out_ver, size_t out_ver_len)
|
||||
{
|
||||
WIN_SAVE_LAST_ERROR; // GetFileVersion*, Ver*
|
||||
WinScopedPreserveLastError s; // GetFileVersion*, Ver*
|
||||
WinScopedDisableWow64Redirection noRedirect;
|
||||
|
||||
const std::string modulePathname = modulePathname_.external_file_string();
|
||||
@ -65,8 +65,6 @@ static LibError ReadVersionString(const OsPath& modulePathname_, char* out_ver,
|
||||
WARN_RETURN(ERR::FAIL);
|
||||
|
||||
strcpy_s(out_ver, out_ver_len, in_ver);
|
||||
|
||||
WIN_RESTORE_LAST_ERROR;
|
||||
return INFO::OK;
|
||||
}
|
||||
|
||||
|
@ -87,6 +87,8 @@ static HandleManager* handleManager;
|
||||
// open fn in async mode and associate handle with fd.
|
||||
int aio_reopen(int fd, const char* fn, int oflag, ...)
|
||||
{
|
||||
WinScopedPreserveLastError s; // CreateFile
|
||||
|
||||
// interpret oflag
|
||||
DWORD access = GENERIC_READ; // assume O_RDONLY
|
||||
DWORD share = FILE_SHARE_READ;
|
||||
@ -105,10 +107,8 @@ int aio_reopen(int fd, const char* fn, int oflag, ...)
|
||||
create = (oflag & O_EXCL)? CREATE_NEW : CREATE_ALWAYS;
|
||||
|
||||
// open file
|
||||
DWORD flags = FILE_FLAG_OVERLAPPED|FILE_FLAG_NO_BUFFERING|FILE_FLAG_SEQUENTIAL_SCAN;
|
||||
WIN_SAVE_LAST_ERROR; // CreateFile
|
||||
HANDLE hFile = CreateFile(fn, access, share, 0, create, flags, 0);
|
||||
WIN_RESTORE_LAST_ERROR;
|
||||
const DWORD flags = FILE_FLAG_OVERLAPPED|FILE_FLAG_NO_BUFFERING|FILE_FLAG_SEQUENTIAL_SCAN;
|
||||
const HANDLE hFile = CreateFile(fn, access, share, 0, create, flags, 0);
|
||||
if(hFile == INVALID_HANDLE_VALUE)
|
||||
WARN_RETURN(-1);
|
||||
|
||||
@ -180,9 +180,8 @@ int open(const char* fn, int oflag, ...)
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
WIN_SAVE_LAST_ERROR; // CreateFile
|
||||
WinScopedPreserveLastError s; // _open's CreateFile
|
||||
int fd = _open(fn, oflag, mode);
|
||||
WIN_RESTORE_LAST_ERROR;
|
||||
|
||||
// none of the above apply; now re-open the file.
|
||||
// note: this is possible because _open defaults to DENY_NONE sharing.
|
||||
@ -273,6 +272,8 @@ public:
|
||||
|
||||
LibError Issue(HANDLE hFile, off_t ofs, void* buf, size_t size, bool isWrite)
|
||||
{
|
||||
WinScopedPreserveLastError s;
|
||||
|
||||
m_hFile = hFile;
|
||||
|
||||
// note: Read-/WriteFile reset m_overlapped.hEvent, so we don't have to.
|
||||
@ -282,7 +283,6 @@ public:
|
||||
|
||||
DWORD bytesTransferred;
|
||||
BOOL ok;
|
||||
WIN_SAVE_LAST_ERROR;
|
||||
if(isWrite)
|
||||
ok = WriteFile(hFile, buf, u64_lo(size), &bytesTransferred, &m_overlapped);
|
||||
else
|
||||
@ -292,7 +292,6 @@ public:
|
||||
ok = TRUE;
|
||||
SetLastError(0);
|
||||
}
|
||||
WIN_RESTORE_LAST_ERROR;
|
||||
return LibError_from_win32(ok);
|
||||
}
|
||||
|
||||
|
@ -130,9 +130,9 @@ static LibError mmap_file_access(int prot, int flags, DWORD& flProtect, DWORD& d
|
||||
|
||||
static LibError mmap_file(void* start, size_t len, int prot, int flags, int fd, off_t ofs, void** pp)
|
||||
{
|
||||
debug_assert(fd != -1); // handled by mmap_mem
|
||||
WinScopedPreserveLastError s;
|
||||
|
||||
WIN_SAVE_LAST_ERROR;
|
||||
debug_assert(fd != -1); // handled by mmap_mem
|
||||
|
||||
HANDLE hFile = HANDLE_from_intptr(_get_osfhandle(fd));
|
||||
if(hFile == INVALID_HANDLE_VALUE)
|
||||
@ -169,7 +169,6 @@ static LibError mmap_file(void* start, size_t len, int prot, int flags, int fd,
|
||||
// slap on correct (more restrictive) permissions.
|
||||
(void)mprotect(p, len, prot);
|
||||
|
||||
WIN_RESTORE_LAST_ERROR;
|
||||
*pp = p;
|
||||
return INFO::OK;
|
||||
}
|
||||
|
@ -296,6 +296,8 @@ static HANDLE HANDLE_from_sem_t(sem_t* sem)
|
||||
|
||||
sem_t* sem_open(const char* name, int oflag, ...)
|
||||
{
|
||||
WinScopedPreserveLastError s;
|
||||
|
||||
const bool create = (oflag & O_CREAT) != 0;
|
||||
const bool exclusive = (oflag & O_EXCL) != 0;
|
||||
|
||||
@ -317,14 +319,12 @@ sem_t* sem_open(const char* name, int oflag, ...)
|
||||
}
|
||||
|
||||
// create or open
|
||||
WIN_SAVE_LAST_ERROR;
|
||||
SetLastError(0);
|
||||
const LONG maxValue = 0x7fffffff;
|
||||
const HANDLE hSemaphore = CreateSemaphore(0, (LONG)initialValue, maxValue, 0);
|
||||
if(hSemaphore == 0)
|
||||
return SEM_FAILED;
|
||||
const bool existed = (GetLastError() == ERROR_ALREADY_EXISTS);
|
||||
WIN_RESTORE_LAST_ERROR;
|
||||
|
||||
// caller insisted on creating anew, but it already existed
|
||||
if(exclusive && existed)
|
||||
|
@ -190,8 +190,7 @@ static LRESULT CALLBACK wndproc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPar
|
||||
// w = h = bpp = 0 => no change.
|
||||
int SDL_SetVideoMode(int w, int h, int bpp, unsigned long flags)
|
||||
{
|
||||
int ret = 0; // assume failure
|
||||
WIN_SAVE_LAST_ERROR; // OpenGL and GDI
|
||||
WinScopedPreserveLastError s; // OpenGL and GDI
|
||||
|
||||
fullscreen = (flags & SDL_FULLSCREEN) != 0;
|
||||
|
||||
@ -199,7 +198,7 @@ int SDL_SetVideoMode(int w, int h, int bpp, unsigned long flags)
|
||||
memset(&dm, 0, sizeof(dm));
|
||||
dm.dmSize = sizeof(dm);
|
||||
EnumDisplaySettings(0, ENUM_CURRENT_SETTINGS, &dm);
|
||||
int cur_w = (int)dm.dmPelsWidth, cur_h = (int)dm.dmPelsHeight;
|
||||
const int cur_w = (int)dm.dmPelsWidth, cur_h = (int)dm.dmPelsHeight;
|
||||
|
||||
// independent of resolution; app must always get bpp it wants
|
||||
dm.dmBitsPerPel = bpp;
|
||||
@ -234,7 +233,7 @@ int SDL_SetVideoMode(int w, int h, int bpp, unsigned long flags)
|
||||
return 0;
|
||||
}
|
||||
|
||||
DWORD windowStyle = fullscreen ? (WS_POPUP|WS_VISIBLE) : WS_VISIBLE | WS_CAPTION|WS_POPUPWINDOW|WS_MINIMIZEBOX;
|
||||
const DWORD windowStyle = fullscreen ? (WS_POPUP|WS_VISIBLE) : WS_VISIBLE | WS_CAPTION|WS_POPUPWINDOW|WS_MINIMIZEBOX;
|
||||
|
||||
// Calculate the size of the outer window, so that the client area has
|
||||
// the desired dimensions.
|
||||
@ -295,20 +294,16 @@ int SDL_SetVideoMode(int w, int h, int bpp, unsigned long flags)
|
||||
|
||||
int pf = ChoosePixelFormat(hDC, &pfd);
|
||||
if(!SetPixelFormat(hDC, pf, &pfd))
|
||||
goto fail;
|
||||
return 0;
|
||||
|
||||
hGLRC = wglCreateContext(hDC);
|
||||
if(!hGLRC)
|
||||
goto fail;
|
||||
return 0;
|
||||
|
||||
if(!wglMakeCurrent(hDC, hGLRC))
|
||||
goto fail;
|
||||
return 0;
|
||||
|
||||
ret = 1;
|
||||
|
||||
fail:
|
||||
WIN_RESTORE_LAST_ERROR;
|
||||
return ret;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@ -357,7 +352,7 @@ SDL_VideoInfo* SDL_GetVideoInfo()
|
||||
|
||||
#ifdef DDRAW
|
||||
|
||||
WIN_SAVE_LAST_ERROR; // DirectDraw
|
||||
WinScopedPreserveLastError s; // DirectDraw
|
||||
|
||||
ONCE({
|
||||
IDirectDraw* dd = 0;
|
||||
@ -374,8 +369,6 @@ SDL_VideoInfo* SDL_GetVideoInfo()
|
||||
}
|
||||
});
|
||||
|
||||
WIN_RESTORE_LAST_ERROR;
|
||||
|
||||
#endif
|
||||
|
||||
return &video_info;
|
||||
@ -392,7 +385,7 @@ int GetVRAMInfo(int& remaining, int& total)
|
||||
int ok = 0;
|
||||
#ifdef DDRAW
|
||||
|
||||
WIN_SAVE_LAST_ERROR; // DirectDraw
|
||||
WinScopedPreserveLastError s; // DirectDraw
|
||||
|
||||
IDirectDraw* dd = 0;
|
||||
HRESULT hr = DirectDrawCreate(0, &dd, 0);
|
||||
@ -410,8 +403,6 @@ int GetVRAMInfo(int& remaining, int& total)
|
||||
dd->Release();
|
||||
}
|
||||
|
||||
WIN_RESTORE_LAST_ERROR;
|
||||
|
||||
#endif
|
||||
|
||||
return ok;
|
||||
|
@ -75,11 +75,32 @@ struct WinScopedLock
|
||||
|
||||
|
||||
//
|
||||
// error codes
|
||||
// errors
|
||||
//
|
||||
|
||||
#define WIN_SAVE_LAST_ERROR DWORD last_err__ = GetLastError();
|
||||
#define WIN_RESTORE_LAST_ERROR STMT(if(last_err__ != 0 && GetLastError() == 0) SetLastError(last_err__););
|
||||
/**
|
||||
* some WinAPI functions SetLastError(0) on success, which is bad because
|
||||
* it can hide previous errors. this class takes care of restoring the
|
||||
* previous value.
|
||||
**/
|
||||
class WinScopedPreserveLastError
|
||||
{
|
||||
public:
|
||||
WinScopedPreserveLastError()
|
||||
: m_lastError(GetLastError())
|
||||
{
|
||||
}
|
||||
|
||||
~WinScopedPreserveLastError()
|
||||
{
|
||||
if(m_lastError != 0 && GetLastError() == 0)
|
||||
SetLastError(m_lastError);
|
||||
}
|
||||
|
||||
private:
|
||||
DWORD m_lastError;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return the LibError equivalent of GetLastError(), or ERR::FAIL if
|
||||
|
Loading…
Reference in New Issue
Block a user