private T PerformWithSettings <T>(Func <JsonSerializerSettings, T> func) { JsonSerializerSettings settings; bool recursive = false; if (currentJsonSettings.Value != null) { // This is a recursive call recursive = true; settings = currentJsonSettings.Value; settings.TraceWriter?.Trace(TraceLevel.Info, "Entering recursive object", null); } else { settings = CreateSettings(); currentJsonSettings.Value = settings; } try { return(func(settings)); } catch (Exception e) { // Don't do our special automatic debug enabling if debug writing is already on if (JSONDebug.ErrorHasOccurred || settings.TraceWriter != null) { throw; } JSONDebug.ErrorHasOccurred = true; if (Settings.Instance.JSONDebugMode == JSONDebug.DebugMode.Automatic) { GD.Print("JSON error happened, retrying with debug printing (mode is automatic), first exception: ", e); currentJsonSettings.Value = null; PerformWithSettings(func); // If we get here, we didn't get another exception... // So we could maybe re-throw the first exception so that we fail like we should GD.PrintErr( "Expected an exception for the second try at JSON operation, but it succeeded, " + "re-throwing the original exception"); throw; } else { throw; } } finally { if (!recursive) { currentJsonSettings.Value = null; if (settings.TraceWriter != null) { JSONDebug.OnTraceFinished(settings.TraceWriter); // This shouldn't get reused so no point in creating a new instance here settings.TraceWriter = null; } } else { settings.TraceWriter?.Trace(TraceLevel.Info, "Exited recursive object", null); } } }