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:
janwas 2007-12-23 12:20:37 +00:00
parent 5bf9bca9ef
commit 2bffecb331
8 changed files with 60 additions and 61 deletions

View File

@ -793,6 +793,8 @@ static ModuleInitState initState;
void h_mgr_init()
{
if(!ModuleShouldInitialize(&initState))
return;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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)

View File

@ -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;

View File

@ -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