diff --git a/Subtrees/beast/modules/beast_core/native/beast_bsd_Threads.cpp b/Subtrees/beast/modules/beast_core/native/beast_bsd_Threads.cpp index 1255f375e..9919a5250 100644 --- a/Subtrees/beast/modules/beast_core/native/beast_bsd_Threads.cpp +++ b/Subtrees/beast/modules/beast_core/native/beast_bsd_Threads.cpp @@ -49,7 +49,8 @@ void Process::setPriority (const ProcessPriority prior) void Process::terminate() { - exit (0); + // http://www.unix.com/man-page/FreeBSD/2/_exit/ + ::_exit (EXIT_FAILURE); } BEAST_API bool BEAST_CALLTYPE beast_isRunningUnderDebugger() diff --git a/Subtrees/beast/modules/beast_core/native/beast_linux_Threads.cpp b/Subtrees/beast/modules/beast_core/native/beast_linux_Threads.cpp index 5ce0db555..edb67d28b 100644 --- a/Subtrees/beast/modules/beast_core/native/beast_linux_Threads.cpp +++ b/Subtrees/beast/modules/beast_core/native/beast_linux_Threads.cpp @@ -49,7 +49,8 @@ void Process::setPriority (const ProcessPriority prior) void Process::terminate() { - exit (0); + // http://linux.die.net/man/2/_exit + ::_exit (EXIT_FAILURE); } BEAST_API bool BEAST_CALLTYPE beast_isRunningUnderDebugger() diff --git a/Subtrees/beast/modules/beast_core/native/beast_mac_Threads.mm b/Subtrees/beast/modules/beast_core/native/beast_mac_Threads.mm index 17f7a382b..572aca272 100644 --- a/Subtrees/beast/modules/beast_core/native/beast_mac_Threads.mm +++ b/Subtrees/beast/modules/beast_core/native/beast_mac_Threads.mm @@ -55,7 +55,8 @@ void Process::lowerPrivilege() void Process::terminate() { - exit (0); + // https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man2/_exit.2.html + ::_exit(EXIT_FAILURE); } void Process::setPriority (ProcessPriority) diff --git a/Subtrees/beast/modules/beast_core/native/beast_win32_Misc.cpp b/Subtrees/beast/modules/beast_core/native/beast_win32_Misc.cpp deleted file mode 100644 index 4a2f785a2..000000000 --- a/Subtrees/beast/modules/beast_core/native/beast_win32_Misc.cpp +++ /dev/null @@ -1,648 +0,0 @@ -//------------------------------------------------------------------------------ -/* - This file is part of Beast: https://github.com/vinniefalco/Beast - Copyright 2013, Vinnie Falco - - Portions of this file are from JUCE. - Copyright (c) 2013 - Raw Material Software Ltd. - Please visit http://www.juce.com - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ -//============================================================================== - -HWND beast_messageWindowHandle = 0; // (this is used by other parts of the codebase) - -//============================================================================== -#if ! BEAST_USE_INTRINSICS -// In newer compilers, the inline versions of these are used (in beast_Atomic.h), but in -// older ones we have to actually call the ops as win32 functions.. -long beast_InterlockedExchange (volatile long* a, long b) noexcept { return InterlockedExchange (a, b); } -long beast_InterlockedIncrement (volatile long* a) noexcept { return InterlockedIncrement (a); } -long beast_InterlockedDecrement (volatile long* a) noexcept { return InterlockedDecrement (a); } -long beast_InterlockedExchangeAdd (volatile long* a, long b) noexcept { return InterlockedExchangeAdd (a, b); } -long beast_InterlockedCompareExchange (volatile long* a, long b, long c) noexcept { return InterlockedCompareExchange (a, b, c); } - -__int64 beast_InterlockedCompareExchange64 (volatile __int64* value, __int64 newValue, __int64 valueToCompare) noexcept -{ - bassertfalse; // This operation isn't available in old MS compiler versions! - - __int64 oldValue = *value; - if (oldValue == valueToCompare) - *value = newValue; - - return oldValue; -} - -#endif - -//============================================================================== -CriticalSection::CriticalSection() noexcept -{ - // (just to check the MS haven't changed this structure and broken things...) - #if BEAST_VC7_OR_EARLIER - static_bassert (sizeof (CRITICAL_SECTION) <= 24); - #else - static_bassert (sizeof (CRITICAL_SECTION) <= sizeof (internal)); - #endif - - InitializeCriticalSection ((CRITICAL_SECTION*) internal); -} - -CriticalSection::~CriticalSection() noexcept -{ - DeleteCriticalSection ((CRITICAL_SECTION*) internal); -} - -void CriticalSection::enter() const noexcept -{ - EnterCriticalSection ((CRITICAL_SECTION*) internal); -} - -bool CriticalSection::tryEnter() const noexcept -{ - return TryEnterCriticalSection ((CRITICAL_SECTION*) internal) != FALSE; -} - -void CriticalSection::exit() const noexcept -{ - LeaveCriticalSection ((CRITICAL_SECTION*) internal); -} - -//============================================================================== -WaitableEvent::WaitableEvent (const bool manualReset) noexcept - : internal (CreateEvent (0, manualReset ? TRUE : FALSE, FALSE, 0)) -{ -} - -WaitableEvent::~WaitableEvent() noexcept -{ - CloseHandle (internal); -} - -bool WaitableEvent::wait (const int timeOutMillisecs) const noexcept -{ - return WaitForSingleObject (internal, (DWORD) timeOutMillisecs) == WAIT_OBJECT_0; -} - -void WaitableEvent::signal() const noexcept -{ - SetEvent (internal); -} - -void WaitableEvent::reset() const noexcept -{ - ResetEvent (internal); -} - -//============================================================================== -void BEAST_API beast_threadEntryPoint (void*); - -static unsigned int __stdcall threadEntryProc (void* userData) -{ - if (beast_messageWindowHandle != 0) - AttachThreadInput (GetWindowThreadProcessId (beast_messageWindowHandle, 0), - GetCurrentThreadId(), TRUE); - - beast_threadEntryPoint (userData); - - _endthreadex (0); - return 0; -} - -void Thread::launchThread() -{ - unsigned int newThreadId; - threadHandle = (void*) _beginthreadex (0, 0, &threadEntryProc, this, 0, &newThreadId); - threadId = (ThreadID) newThreadId; -} - -void Thread::closeThreadHandle() -{ - CloseHandle ((HANDLE) threadHandle); - threadId = 0; - threadHandle = 0; -} - -void Thread::killThread() -{ - if (threadHandle != 0) - { - #if BEAST_DEBUG - OutputDebugStringA ("** Warning - Forced thread termination **\n"); - #endif - TerminateThread (threadHandle, 0); - } -} - -void Thread::setCurrentThreadName (const String& name) -{ - #if BEAST_DEBUG && BEAST_MSVC - struct - { - DWORD dwType; - LPCSTR szName; - DWORD dwThreadID; - DWORD dwFlags; - } info; - - info.dwType = 0x1000; - info.szName = name.toUTF8(); - info.dwThreadID = GetCurrentThreadId(); - info.dwFlags = 0; - - __try - { - RaiseException (0x406d1388 /*MS_VC_EXCEPTION*/, 0, sizeof (info) / sizeof (ULONG_PTR), (ULONG_PTR*) &info); - } - __except (EXCEPTION_CONTINUE_EXECUTION) - {} - #else - (void) name; - #endif -} - -Thread::ThreadID Thread::getCurrentThreadId() -{ - return (ThreadID) (pointer_sized_int) GetCurrentThreadId(); -} - -bool Thread::setThreadPriority (void* handle, int priority) -{ - int pri = THREAD_PRIORITY_TIME_CRITICAL; - - if (priority < 1) pri = THREAD_PRIORITY_IDLE; - else if (priority < 2) pri = THREAD_PRIORITY_LOWEST; - else if (priority < 5) pri = THREAD_PRIORITY_BELOW_NORMAL; - else if (priority < 7) pri = THREAD_PRIORITY_NORMAL; - else if (priority < 9) pri = THREAD_PRIORITY_ABOVE_NORMAL; - else if (priority < 10) pri = THREAD_PRIORITY_HIGHEST; - - if (handle == 0) - handle = GetCurrentThread(); - - return SetThreadPriority (handle, pri) != FALSE; -} - -void Thread::setCurrentThreadAffinityMask (const uint32 affinityMask) -{ - SetThreadAffinityMask (GetCurrentThread(), affinityMask); -} - -//============================================================================== -struct SleepEvent -{ - SleepEvent() noexcept - : handle (CreateEvent (nullptr, FALSE, FALSE, - #if BEAST_DEBUG - _T("BEAST Sleep Event"))) - #else - nullptr)) - #endif - {} - - ~SleepEvent() noexcept - { - CloseHandle (handle); - handle = 0; - } - - HANDLE handle; -}; - -static SleepEvent sleepEvent; - -void BEAST_CALLTYPE Thread::sleep (const int millisecs) -{ - if (millisecs >= 10 || sleepEvent.handle == 0) - { - Sleep ((DWORD) millisecs); - } - else - { - // unlike Sleep() this is guaranteed to return to the current thread after - // the time expires, so we'll use this for short waits, which are more likely - // to need to be accurate - WaitForSingleObject (sleepEvent.handle, (DWORD) millisecs); - } -} - -void Thread::yield() -{ - Sleep (0); -} - -//============================================================================== -static int lastProcessPriority = -1; - -// called by WindowDriver because Windows does weird things to process priority -// when you swap apps, and this forces an update when the app is brought to the front. -void beast_repeatLastProcessPriority() -{ - if (lastProcessPriority >= 0) // (avoid changing this if it's not been explicitly set by the app..) - { - DWORD p; - - switch (lastProcessPriority) - { - case Process::LowPriority: p = IDLE_PRIORITY_CLASS; break; - case Process::NormalPriority: p = NORMAL_PRIORITY_CLASS; break; - case Process::HighPriority: p = HIGH_PRIORITY_CLASS; break; - case Process::RealtimePriority: p = REALTIME_PRIORITY_CLASS; break; - default: bassertfalse; return; // bad priority value - } - - SetPriorityClass (GetCurrentProcess(), p); - } -} - -void Process::setPriority (ProcessPriority prior) -{ - if (lastProcessPriority != (int) prior) - { - lastProcessPriority = (int) prior; - beast_repeatLastProcessPriority(); - } -} - -BEAST_API bool BEAST_CALLTYPE beast_isRunningUnderDebugger() -{ - return IsDebuggerPresent() != FALSE; -} - -bool BEAST_CALLTYPE Process::isRunningUnderDebugger() -{ - return beast_isRunningUnderDebugger(); -} - -BEAST_API void BEAST_CALLTYPE Process::breakPoint () -{ -#if BEAST_DEBUG - if (beast_isRunningUnderDebugger ()) - beast_breakDebugger; - -#else - bassertfalse; - -#endif -} - -//------------------------------------------------------------------------------ - -static void* currentModuleHandle = nullptr; - -void* Process::getCurrentModuleInstanceHandle() noexcept -{ - if (currentModuleHandle == nullptr) - currentModuleHandle = GetModuleHandleA (nullptr); - - return currentModuleHandle; -} - -void Process::setCurrentModuleInstanceHandle (void* const newHandle) noexcept -{ - currentModuleHandle = newHandle; -} - -void Process::raisePrivilege() -{ - bassertfalse; // xxx not implemented -} - -void Process::lowerPrivilege() -{ - bassertfalse; // xxx not implemented -} - -void Process::terminate() -{ - #if BEAST_MSVC && BEAST_CHECK_MEMORY_LEAKS - _CrtDumpMemoryLeaks(); - #endif - - // bullet in the head in case there's a problem shutting down.. - ExitProcess (0); -} - -bool beast_isRunningInWine() -{ - HMODULE ntdll = GetModuleHandleA ("ntdll"); - return ntdll != 0 && GetProcAddress (ntdll, "wine_get_version") != nullptr; -} - -//============================================================================== -bool DynamicLibrary::open (const String& name) -{ - close(); - - BEAST_TRY - { - handle = LoadLibrary (name.toWideCharPointer()); - } - BEAST_CATCH_ALL - - return handle != nullptr; -} - -void DynamicLibrary::close() -{ - BEAST_TRY - { - if (handle != nullptr) - { - FreeLibrary ((HMODULE) handle); - handle = nullptr; - } - } - BEAST_CATCH_ALL -} - -void* DynamicLibrary::getFunction (const String& functionName) noexcept -{ - return handle != nullptr ? (void*) GetProcAddress ((HMODULE) handle, functionName.toUTF8()) // (void* cast is required for mingw) - : nullptr; -} - - -//============================================================================== -class InterProcessLock::Pimpl -{ -public: - Pimpl (String name, const int timeOutMillisecs) - : handle (0), refCount (1) - { - name = name.replaceCharacter ('\\', '/'); - handle = CreateMutexW (0, TRUE, ("Global\\" + name).toWideCharPointer()); - - // Not 100% sure why a global mutex sometimes can't be allocated, but if it fails, fall back to - // a local one. (A local one also sometimes fails on other machines so neither type appears to be - // universally reliable) - if (handle == 0) - handle = CreateMutexW (0, TRUE, ("Local\\" + name).toWideCharPointer()); - - if (handle != 0 && GetLastError() == ERROR_ALREADY_EXISTS) - { - if (timeOutMillisecs == 0) - { - close(); - return; - } - - switch (WaitForSingleObject (handle, timeOutMillisecs < 0 ? INFINITE : timeOutMillisecs)) - { - case WAIT_OBJECT_0: - case WAIT_ABANDONED: - break; - - case WAIT_TIMEOUT: - default: - close(); - break; - } - } - } - - ~Pimpl() - { - close(); - } - - void close() - { - if (handle != 0) - { - ReleaseMutex (handle); - CloseHandle (handle); - handle = 0; - } - } - - HANDLE handle; - int refCount; -}; - -InterProcessLock::InterProcessLock (const String& name_) - : name (name_) -{ -} - -InterProcessLock::~InterProcessLock() -{ -} - -bool InterProcessLock::enter (const int timeOutMillisecs) -{ - const ScopedLock sl (lock); - - if (pimpl == nullptr) - { - pimpl = new Pimpl (name, timeOutMillisecs); - - if (pimpl->handle == 0) - pimpl = nullptr; - } - else - { - pimpl->refCount++; - } - - return pimpl != nullptr; -} - -void InterProcessLock::exit() -{ - const ScopedLock sl (lock); - - // Trying to release the lock too many times! - bassert (pimpl != nullptr); - - if (pimpl != nullptr && --(pimpl->refCount) == 0) - pimpl = nullptr; -} - -//============================================================================== -class ChildProcess::ActiveProcess -{ -public: - ActiveProcess (const String& command) - : ok (false), readPipe (0), writePipe (0) - { - SECURITY_ATTRIBUTES securityAtts = { 0 }; - securityAtts.nLength = sizeof (securityAtts); - securityAtts.bInheritHandle = TRUE; - - if (CreatePipe (&readPipe, &writePipe, &securityAtts, 0) - && SetHandleInformation (readPipe, HANDLE_FLAG_INHERIT, 0)) - { - STARTUPINFOW startupInfo = { 0 }; - startupInfo.cb = sizeof (startupInfo); - startupInfo.hStdError = writePipe; - startupInfo.hStdOutput = writePipe; - startupInfo.dwFlags = STARTF_USESTDHANDLES; - - ok = CreateProcess (nullptr, const_cast (command.toWideCharPointer()), - nullptr, nullptr, TRUE, CREATE_NO_WINDOW | CREATE_UNICODE_ENVIRONMENT, - nullptr, nullptr, &startupInfo, &processInfo) != FALSE; - } - } - - ~ActiveProcess() - { - if (ok) - { - CloseHandle (processInfo.hThread); - CloseHandle (processInfo.hProcess); - } - - if (readPipe != 0) - CloseHandle (readPipe); - - if (writePipe != 0) - CloseHandle (writePipe); - } - - bool isRunning() const - { - return WaitForSingleObject (processInfo.hProcess, 0) != WAIT_OBJECT_0; - } - - int read (void* dest, int numNeeded) const - { - int total = 0; - - while (ok && numNeeded > 0) - { - DWORD available = 0; - - if (! PeekNamedPipe ((HANDLE) readPipe, nullptr, 0, nullptr, &available, nullptr)) - break; - - const int numToDo = bmin ((int) available, numNeeded); - - if (available == 0) - { - if (! isRunning()) - break; - - Thread::yield(); - } - else - { - DWORD numRead = 0; - if (! ReadFile ((HANDLE) readPipe, dest, numToDo, &numRead, nullptr)) - break; - - total += numRead; - dest = addBytesToPointer (dest, numRead); - numNeeded -= numRead; - } - } - - return total; - } - - bool killProcess() const - { - return TerminateProcess (processInfo.hProcess, 0) != FALSE; - } - - bool ok; - -private: - HANDLE readPipe, writePipe; - PROCESS_INFORMATION processInfo; - - BEAST_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ActiveProcess) -}; - -bool ChildProcess::start (const String& command) -{ - activeProcess = new ActiveProcess (command); - - if (! activeProcess->ok) - activeProcess = nullptr; - - return activeProcess != nullptr; -} - -bool ChildProcess::start (const StringArray& args) -{ - return start (args.joinIntoString (" ")); -} - -bool ChildProcess::isRunning() const -{ - return activeProcess != nullptr && activeProcess->isRunning(); -} - -int ChildProcess::readProcessOutput (void* dest, int numBytes) -{ - return activeProcess != nullptr ? activeProcess->read (dest, numBytes) : 0; -} - -bool ChildProcess::kill() -{ - return activeProcess == nullptr || activeProcess->killProcess(); -} - -//============================================================================== -struct HighResolutionTimer::Pimpl -{ - Pimpl (HighResolutionTimer& t) noexcept : owner (t), periodMs (0) - { - } - - ~Pimpl() - { - bassert (periodMs == 0); - } - - void start (int newPeriod) - { - if (newPeriod != periodMs) - { - stop(); - periodMs = newPeriod; - - TIMECAPS tc; - if (timeGetDevCaps (&tc, sizeof (tc)) == TIMERR_NOERROR) - { - const int actualPeriod = blimit ((int) tc.wPeriodMin, (int) tc.wPeriodMax, newPeriod); - - timerID = timeSetEvent (actualPeriod, tc.wPeriodMin, callbackFunction, (DWORD_PTR) this, - TIME_PERIODIC | TIME_CALLBACK_FUNCTION | 0x100 /*TIME_KILL_SYNCHRONOUS*/); - } - } - } - - void stop() - { - periodMs = 0; - timeKillEvent (timerID); - } - - HighResolutionTimer& owner; - int periodMs; - -private: - unsigned int timerID; - - static void __stdcall callbackFunction (UINT, UINT, DWORD_PTR userInfo, DWORD_PTR, DWORD_PTR) - { - if (Pimpl* const timer = reinterpret_cast (userInfo)) - if (timer->periodMs != 0) - timer->owner.hiResTimerCallback(); - } - - BEAST_DECLARE_NON_COPYABLE (Pimpl) -};