Merge branch 'fix/linux-file-picker' into 'master'

Linux: Fix file picker not launching from disabling core dumps

See merge request [ryubing/ryujinx!249](https://git.ryujinx.app/ryubing/ryujinx/-/merge_requests/249)
This commit is contained in:
KeatonTheBot
2026-02-19 11:02:29 -06:00
9 changed files with 124 additions and 2 deletions

View File

@@ -22,10 +22,11 @@ namespace Ryujinx.Common.Utilities
}
// "dumpable" attribute of the calling process
private const int PR_GET_DUMPABLE = 3;
private const int PR_SET_DUMPABLE = 4;
[DllImport("libc", SetLastError = true)]
private static extern int prctl(int option, int arg2);
[LibraryImport("libc", SetLastError = true)]
private static partial int prctl(int option, int arg2);
public static void SetCoreDumpable(bool dumpable)
{
@@ -36,5 +37,13 @@ namespace Ryujinx.Common.Utilities
Debug.Assert(result == 0);
}
}
// Use the below line to display dumpable status in the console:
// Console.WriteLine($"{OsUtils.IsCoreDumpable()}");
public static bool IsCoreDumpable()
{
int result = prctl(PR_GET_DUMPABLE, 0);
return result == 1;
}
}
}

View File

@@ -18,6 +18,7 @@ using Ryujinx.Ava.UI.Windows;
using Ryujinx.Ava.Utilities;
using Ryujinx.Common.Helper;
using Ryujinx.Common.Logging;
using Ryujinx.Common.Utilities;
using Ryujinx.HLE.FileSystem;
using Ryujinx.HLE.HOS.Services.Account.Acc;
using Ryujinx.HLE.Loaders.Processes.Extensions;
@@ -410,6 +411,8 @@ namespace Ryujinx.Ava.Common
public static async Task ExtractAoc(IStorageProvider storageProvider, string updateFilePath, string updateName)
{
OsUtils.SetCoreDumpable(true);
Gommon.Optional<IStorageFolder> result = await storageProvider.OpenSingleFolderPickerAsync(new FolderPickerOpenOptions
{
Title = LocaleManager.Instance[LocaleKeys.FolderDialogExtractTitle]
@@ -419,10 +422,17 @@ namespace Ryujinx.Ava.Common
return;
ExtractAoc(result.Value.Path.LocalPath, updateFilePath, updateName);
if (!Program.CoreDumpArg)
{
OsUtils.SetCoreDumpable(false);
}
}
public static async Task ExtractSection(IStorageProvider storageProvider, NcaSectionType ncaSectionType, string titleFilePath, string titleName, int programIndex = 0)
{
OsUtils.SetCoreDumpable(true);
Gommon.Optional<IStorageFolder> result = await storageProvider.OpenSingleFolderPickerAsync(new FolderPickerOpenOptions
{
Title = LocaleManager.Instance[LocaleKeys.FolderDialogExtractTitle]
@@ -432,6 +442,11 @@ namespace Ryujinx.Ava.Common
return;
ExtractSection(result.Value.Path.LocalPath, ncaSectionType, titleFilePath, titleName, programIndex);
if (!Program.CoreDumpArg)
{
OsUtils.SetCoreDumpable(false);
}
}
public static (Result? result, bool canceled) CopyDirectory(FileSystemClient fs, string sourcePath, string destPath, CancellationToken token)

View File

@@ -42,6 +42,7 @@ namespace Ryujinx.Ava
public static bool PreviewerDetached { get; private set; }
public static bool UseHardwareAcceleration { get; private set; }
public static string BackendThreadingArg { get; private set; }
public static bool CoreDumpArg { get; private set; }
private const uint MbIconwarning = 0x30;
@@ -81,6 +82,8 @@ namespace Ryujinx.Ava
bool noGuiArg = ConsumeCommandLineArgument(ref args, "--no-gui") || ConsumeCommandLineArgument(ref args, "nogui");
bool coreDumpArg = ConsumeCommandLineArgument(ref args, "--core-dumps");
CoreDumpArg = coreDumpArg;
// TODO: Ryujinx causes core dumps on Linux when it exits "uncleanly", eg. through an unhandled exception.
// This is undesirable and causes very odd behavior during development (the process stops responding,
// the .NET debugger freezes or suddenly detaches, /tmp/ gets filled etc.), unless explicitly requested by the user.

View File

@@ -8,6 +8,7 @@ using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Common.Models;
using Ryujinx.Ava.Systems.AppLibrary;
using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Common.Utilities;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
@@ -128,6 +129,8 @@ namespace Ryujinx.Ava.UI.ViewModels
public async void Add()
{
OsUtils.SetCoreDumpable(true);
IReadOnlyList<IStorageFile> result = await _storageProvider.OpenFilePickerAsync(new FilePickerOpenOptions
{
Title = LocaleManager.Instance[LocaleKeys.SelectDlcDialogTitle],
@@ -158,6 +161,11 @@ namespace Ryujinx.Ava.UI.ViewModels
{
await ShowNewDlcAddedDialog(totalDlcAdded);
}
if (!Program.CoreDumpArg)
{
OsUtils.SetCoreDumpable(false);
}
}
private bool AddDownloadableContent(string path, out int numDlcAdded)

View File

@@ -1266,6 +1266,8 @@ namespace Ryujinx.Ava.UI.ViewModels
private async Task LoadContentFromFolder(LocaleKeys localeMessageAddedKey, LocaleKeys localeMessageRemovedKey,
LoadContentFromFolderDelegate onDirsSelected, LocaleKeys dirSelectDialogTitle)
{
OsUtils.SetCoreDumpable(true);
Optional<IReadOnlyList<IStorageFolder>> result =
await StorageProvider.OpenMultiFolderPickerAsync(
new FolderPickerOpenOptions { Title = LocaleManager.Instance[dirSelectDialogTitle] });
@@ -1293,6 +1295,11 @@ namespace Ryujinx.Ava.UI.ViewModels
(int)Symbol.Checkmark);
});
}
if (!Program.CoreDumpArg)
{
OsUtils.SetCoreDumpable(false);
}
}
#endregion
@@ -1355,6 +1362,8 @@ namespace Ryujinx.Ava.UI.ViewModels
public async Task InstallFirmwareFromFile()
{
OsUtils.SetCoreDumpable(true);
Optional<IStorageFile> result = await StorageProvider.OpenSingleFilePickerAsync(new FilePickerOpenOptions
{
FileTypeFilter = new List<FilePickerFileType>
@@ -1384,20 +1393,34 @@ namespace Ryujinx.Ava.UI.ViewModels
{
await HandleFirmwareInstallation(result.Value.Path.LocalPath);
}
if (!Program.CoreDumpArg)
{
OsUtils.SetCoreDumpable(false);
}
}
public async Task InstallFirmwareFromFolder()
{
OsUtils.SetCoreDumpable(true);
Optional<IStorageFolder> result = await StorageProvider.OpenSingleFolderPickerAsync();
if (result.HasValue)
{
await HandleFirmwareInstallation(result.Value.Path.LocalPath);
}
if (!Program.CoreDumpArg)
{
OsUtils.SetCoreDumpable(false);
}
}
public async Task InstallKeysFromFile()
{
OsUtils.SetCoreDumpable(true);
Optional<IStorageFile> result = await StorageProvider.OpenSingleFilePickerAsync(new FilePickerOpenOptions
{
FileTypeFilter = new List<FilePickerFileType>
@@ -1415,16 +1438,28 @@ namespace Ryujinx.Ava.UI.ViewModels
{
await HandleKeysInstallation(result.Value.Path.LocalPath);
}
if (!Program.CoreDumpArg)
{
OsUtils.SetCoreDumpable(false);
}
}
public async Task InstallKeysFromFolder()
{
OsUtils.SetCoreDumpable(true);
Optional<IStorageFolder> result = await StorageProvider.OpenSingleFolderPickerAsync();
if (result.HasValue)
{
await HandleKeysInstallation(result.Value.Path.LocalPath);
}
if (!Program.CoreDumpArg)
{
OsUtils.SetCoreDumpable(false);
}
}
public void OpenRyujinxFolder()
@@ -1528,6 +1563,8 @@ namespace Ryujinx.Ava.UI.ViewModels
public async Task OpenFile()
{
OsUtils.SetCoreDumpable(true);
Optional<IStorageFile> result = await StorageProvider.OpenSingleFilePickerAsync(new FilePickerOpenOptions
{
Title = LocaleManager.Instance[LocaleKeys.LoadApplicationFromFileDialogTitle],
@@ -1599,6 +1636,11 @@ namespace Ryujinx.Ava.UI.ViewModels
LocaleManager.Instance[LocaleKeys.MenuBarFileOpenFromFileError]);
}
}
if (!Program.CoreDumpArg)
{
OsUtils.SetCoreDumpable(false);
}
}
public async Task LoadDlcFromFolder()
@@ -1621,6 +1663,8 @@ namespace Ryujinx.Ava.UI.ViewModels
public async Task OpenFolder()
{
OsUtils.SetCoreDumpable(true);
Optional<IStorageFolder> result = await StorageProvider.OpenSingleFolderPickerAsync(
new FolderPickerOpenOptions
{
@@ -1636,6 +1680,11 @@ namespace Ryujinx.Ava.UI.ViewModels
await LoadApplication(applicationData);
}
if (!Program.CoreDumpArg)
{
OsUtils.SetCoreDumpable(false);
}
}
public static bool InitializeUserConfig(ApplicationData application)
@@ -1843,6 +1892,8 @@ namespace Ryujinx.Ava.UI.ViewModels
public async Task OpenBinFile()
{
OsUtils.SetCoreDumpable(true);
if (AppHost.Device.System.SearchingForAmiibo(out _) && IsGameRunning)
{
Optional<IStorageFile> result = await StorageProvider.OpenSingleFilePickerAsync(
@@ -1862,6 +1913,11 @@ namespace Ryujinx.Ava.UI.ViewModels
{
AppHost.Device.System.ScanAmiiboFromBin(result.Value.Path.LocalPath);
}
if (!Program.CoreDumpArg)
{
OsUtils.SetCoreDumpable(false);
}
}
}

View File

@@ -288,6 +288,8 @@ namespace Ryujinx.Ava.UI.ViewModels
public async void Add()
{
OsUtils.SetCoreDumpable(true);
IReadOnlyList<IStorageFolder> result = await _storageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions
{
Title = LocaleManager.Instance[LocaleKeys.SelectModDialogTitle],
@@ -298,6 +300,11 @@ namespace Ryujinx.Ava.UI.ViewModels
{
AddMod(new DirectoryInfo(folder.Path.LocalPath));
}
if (!Program.CoreDumpArg)
{
OsUtils.SetCoreDumpable(false);
}
}
public void DeleteAll()

View File

@@ -7,6 +7,7 @@ using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Common.Models;
using Ryujinx.Ava.Systems.AppLibrary;
using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Common.Utilities;
using System.Collections.Generic;
using System.IO;
using System.Linq;
@@ -148,6 +149,8 @@ namespace Ryujinx.Ava.UI.ViewModels
public async Task Add()
{
OsUtils.SetCoreDumpable(true);
IReadOnlyList<IStorageFile> result = await _storageProvider.OpenFilePickerAsync(new FilePickerOpenOptions
{
AllowMultiple = true,
@@ -177,6 +180,11 @@ namespace Ryujinx.Ava.UI.ViewModels
{
await ShowNewUpdatesAddedDialog(totalUpdatesAdded);
}
if (!Program.CoreDumpArg)
{
OsUtils.SetCoreDumpable(false);
}
}
public void Save()

View File

@@ -7,6 +7,7 @@ using Ryujinx.Ava.UI.Controls;
using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.Ava.Utilities;
using Ryujinx.Common.Utilities;
using System.Collections.Generic;
using System.IO;
using System.Linq;
@@ -27,6 +28,8 @@ namespace Ryujinx.Ava.UI.Views.Settings
private async Task AddDirButton(TextBox addDirBox, AvaloniaList<string> directories)
{
OsUtils.SetCoreDumpable(true);
string path = addDirBox.Text;
if (!string.IsNullOrWhiteSpace(path) && Directory.Exists(path) && !directories.Contains(path))
@@ -48,6 +51,11 @@ namespace Ryujinx.Ava.UI.Views.Settings
ViewModel.GameListNeedsRefresh = true;
}
}
if (!Program.CoreDumpArg)
{
OsUtils.SetCoreDumpable(false);
}
}
private void RemoveGameDirButton_OnClick(object sender, RoutedEventArgs e)

View File

@@ -8,6 +8,7 @@ using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.UI.Controls;
using Ryujinx.Ava.UI.Models;
using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.Common.Utilities;
using Ryujinx.HLE.FileSystem;
using SkiaSharp;
using System.Collections.Generic;
@@ -62,6 +63,8 @@ namespace Ryujinx.Ava.UI.Views.User
private async void Import_OnClick(object sender, RoutedEventArgs e)
{
OsUtils.SetCoreDumpable(true);
IReadOnlyList<IStorageFile> result = await ((Window)this.GetVisualRoot()!).StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions
{
AllowMultiple = false,
@@ -81,6 +84,11 @@ namespace Ryujinx.Ava.UI.Views.User
_profile.Image = ProcessProfileImage(File.ReadAllBytes(result[0].Path.LocalPath));
_parent.GoBack();
}
if (!Program.CoreDumpArg)
{
OsUtils.SetCoreDumpable(false);
}
}
private void GoBack(object sender, RoutedEventArgs e)