Browse Source

Added a bunch of checks to streamline upgrades

pull/44/head 4.0.2
Anairkoen Schno 4 years ago
parent
commit
529e8de464
5 changed files with 91 additions and 47 deletions
  1. +12
    -3
      Doorstop/Proxy/main.c
  2. +1
    -0
      Doorstop/Proxy/proxy.def
  3. +17
    -11
      IPA.Loader/Config/ConfigRuntime.cs
  4. +28
    -12
      IPA.Loader/Config/Stores/GeneratedStoreImpl/IGeneratedStore.cs
  5. +33
    -21
      IPA.Loader/Utilities/CriticalSection.cs

+ 12
- 3
Doorstop/Proxy/main.c View File

@ -38,8 +38,14 @@ EXTERN_C IMAGE_DOS_HEADER __ImageBase; // This is provided by MSVC with the info
HANDLE unhandledMutex;
void ownMonoJitParseOptions(int argc, char * argv[]);
BOOL setOptions = FALSE;
BOOL shouldBreakOnUnhandledException = TRUE;
void unhandledException(void* exc, void* data)
__declspec(dllexport) void SetIgnoreUnhandledExceptions(BOOL ignore)
{
shouldBreakOnUnhandledException = ignore;
}
void unhandledException(void* exc, void* data)
{
WaitForSingleObject(unhandledMutex, INFINITE);
@ -86,11 +92,14 @@ void unhandledException(void* exc, void* data)
MultiByteToWideChar(CP_UTF8, 0, str, -1, wstr, len);*/
wchar_t* wstr = mono_string_to_utf16(mstr);
if (shouldBreakOnUnhandledException)
{
#ifdef _VERBOSE
ASSERT(FALSE, L"Uncaught exception; see doorstop.log for details");
ASSERT(FALSE, L"Uncaught exception; see doorstop.log for details");
#else
ASSERT_F(FALSE, L"Uncaught exception: %wS", wstr);
ASSERT_F(FALSE, L"Uncaught exception: %wS", wstr);
#endif
}
mono_free(wstr);
mono_free(str);


+ 1
- 0
Doorstop/Proxy/proxy.def View File

@ -52,3 +52,4 @@ EXPORTS
WinHttpWriteData @50
SetGetMessageHook @51
SetPeekMessageHook @52
SetIgnoreUnhandledExceptions @53

+ 17
- 11
IPA.Loader/Config/ConfigRuntime.cs View File

@ -64,17 +64,23 @@ namespace IPA.Config
=> ShutdownRuntime();
internal static void ShutdownRuntime()
{
watcherTrackConfigs.Clear();
var watchList = watchers.ToArray();
watchers.Clear();
foreach (var pair in watchList)
pair.Value.EnableRaisingEvents = false;
loadScheduler.Join(); // we can wait for the loads to finish
saveThread.Abort(); // eww, but i don't like any of the other potential solutions
SaveAll();
try
{
watcherTrackConfigs.Clear();
var watchList = watchers.ToArray();
watchers.Clear();
foreach (var pair in watchList)
pair.Value.EnableRaisingEvents = false;
loadScheduler.Join(); // we can wait for the loads to finish
saveThread.Abort(); // eww, but i don't like any of the other potential solutions
SaveAll();
}
catch
{
}
}
public static void RegisterConfig(Config cfg)


+ 28
- 12
IPA.Loader/Config/Stores/GeneratedStoreImpl/IGeneratedStore.cs View File

@ -59,7 +59,18 @@ namespace IPA.Config.Stores
internal static MethodInfo ImplSignalChangedMethod = typeof(Impl).GetMethod(nameof(ImplSignalChanged));
public static void ImplSignalChanged(IGeneratedStore s) => FindImpl(s).SignalChanged();
public void SignalChanged() => resetEvent.Set();
public void SignalChanged()
{
try
{
resetEvent.Set();
}
catch (ObjectDisposedException e)
{
Logger.config.Error($"ObjectDisposedException while signalling a change for generated store {generated?.GetType()}");
Logger.config.Error(e);
}
}
internal static MethodInfo ImplInvokeChangedMethod = typeof(Impl).GetMethod(nameof(ImplInvokeChanged));
public static void ImplInvokeChanged(IGeneratedStore s) => FindImpl(s).InvokeChanged();
@ -131,18 +142,23 @@ namespace IPA.Config.Stores
public void Dispose() => Dispose(true);
private void Dispose(bool addToStore)
{
if (data.owns)
{
data.impl.inChangeTransaction = false;
data.impl.InvokeChanged();
}
{
if (data.owns)
{
data.impl.inChangeTransaction = false;
data.impl.InvokeChanged();
}
data.nested?.Dispose();
if (data.ownsWrite)
data.impl.ReleaseWrite();
if (addToStore)
freeTransactionObjs.Push(this);
try
{
if (data.ownsWrite)
data.impl.ReleaseWrite();
}
catch
{
}
if (addToStore)
freeTransactionObjs.Push(this);
}
~ChangeTransactionObj() => Dispose(false);


+ 33
- 21
IPA.Loader/Utilities/CriticalSection.cs View File

@ -35,6 +35,14 @@ namespace IPA.Utilities
Win32.SetConsoleCtrlHandler(registeredHandler, false);
Win32.SetConsoleCtrlHandler(registeredHandler, true);
WinHttp.SetPeekMessageHook(PeekMessageHook);
AppDomain.CurrentDomain.ProcessExit -= OnProcessExit;
AppDomain.CurrentDomain.ProcessExit += OnProcessExit;
}
private static void OnProcessExit(object sender, EventArgs args)
{
WinHttp.SetIgnoreUnhandledExceptions(true);
}
private static class WinHttp
@ -52,7 +60,11 @@ namespace IPA.Utilities
[DllImport("bsipa-doorstop")]
public static extern void SetPeekMessageHook(
[MarshalAs(UnmanagedType.FunctionPtr)]
PeekMessageHook hook);
PeekMessageHook hook);
[DllImport("bsipa-doorstop")]
public static extern void SetIgnoreUnhandledExceptions(
[MarshalAs(UnmanagedType.Bool)] bool ignore);
}
private static Win32.ConsoleCtrlDelegate _handler = null;
@ -106,29 +118,29 @@ namespace IPA.Utilities
private static volatile bool exitRecieved = false;
/// <summary>
/// A struct that allows <c>using</c> blocks to manage an execute section.
/// <summary>
/// A struct that allows <c>using</c> blocks to manage an execute section.
/// </summary>
public struct AutoExecuteSection : IDisposable
{
private readonly bool constructed;
internal AutoExecuteSection(bool val)
{
constructed = val && !isInExecuteSection;
if (constructed)
EnterExecuteSection();
}
void IDisposable.Dispose()
{
if (constructed)
ExitExecuteSection();
}
public struct AutoExecuteSection : IDisposable
{
private readonly bool constructed;
internal AutoExecuteSection(bool val)
{
constructed = val && !isInExecuteSection;
if (constructed)
EnterExecuteSection();
}
void IDisposable.Dispose()
{
if (constructed)
ExitExecuteSection();
}
}
/// <summary>
/// Creates an <see cref="AutoExecuteSection"/> for automated management of an execute section.
/// </summary>
/// <summary>
/// Creates an <see cref="AutoExecuteSection"/> for automated management of an execute section.
/// </summary>
/// <returns>the new <see cref="AutoExecuteSection"/> that manages the section</returns>
public static AutoExecuteSection ExecuteSection() => new AutoExecuteSection(true);


Loading…
Cancel
Save