fix: report Linux TUN startup failures (#10556)

This commit is contained in:
Hsia97
2026-11-14 11:11:29 +08:00
committed by GitHub
parent 9c7c169056
commit 18de5da98a
3 changed files with 88 additions and 22 deletions
@@ -0,0 +1,36 @@
namespace ServiceLib.Tests.Handler;
public class CoreConfigHandlerTests
{
[Test]
public async Task GenerateClientConfig_CustomProfileWithMissingSource_ShouldIncludeSourcePath()
{
var sourcePath = Path.Combine(Path.GetTempPath(), $"v2rayN-missing-{Guid.NewGuid():N}.json");
var outputPath = Path.Combine(Path.GetTempPath(), $"v2rayN-output-{Guid.NewGuid():N}.json");
var node = new ProfileItem
{
ConfigType = EConfigType.Custom,
Address = sourcePath,
Remarks = "missing custom config",
};
var context = new CoreConfigContext
{
Node = node,
RunCoreType = ECoreType.Xray,
};
try
{
var result = await CoreConfigHandler.GenerateClientConfig(context, outputPath);
await result.Success.Should().BeFalse();
await result.Msg.Should().Contain(ResUI.FailedReadConfiguration);
await result.Msg.Should().Contain(sourcePath);
await File.Exists(outputPath).Should().BeFalse();
}
finally
{
File.Delete(outputPath);
}
}
}
@@ -65,7 +65,9 @@ public static class CoreConfigHandler
}
if (!File.Exists(addressFileName))
{
ret.Msg = ResUI.FailedGenDefaultConfiguration;
var message = $"{ResUI.FailedReadConfiguration}: {addressFileName}";
Logging.SaveLog($"{_tag}: {message}");
ret.Msg = message;
return ret;
}
File.Copy(addressFileName, fileName);
@@ -74,7 +76,9 @@ public static class CoreConfigHandler
//check again
if (!File.Exists(fileName))
{
ret.Msg = ResUI.FailedGenDefaultConfiguration;
var message = $"{ResUI.FailedReadConfiguration}: {fileName}";
Logging.SaveLog($"{_tag}: {message}");
ret.Msg = message;
return ret;
}
+46 -20
View File
@@ -91,9 +91,19 @@ public class CoreManager
await WindowsUtils.RemoveTunDevice();
}
await CoreStart(mainContext);
if (!await CoreStart(mainContext))
{
return;
}
await WaitForProxyPort(preContext);
await CoreStartPreService(preContext);
if (!await CoreStartPreService(preContext))
{
// Keep the ordinary proxy core available when only the optional TUN
// protection core failed. The error is reported above and the caller
// must not treat this as a successful TUN startup.
return;
}
AppManager.Instance.RunningCoreType = preContext?.RunCoreType ?? mainContext.RunCoreType;
@@ -176,7 +186,7 @@ public class CoreManager
#region Private
private async Task CoreStart(CoreConfigContext context)
private async Task<bool> CoreStart(CoreConfigContext context)
{
var node = context.Node;
var coreType = AppManager.Instance.GetCoreType(node, node.ConfigType);
@@ -186,29 +196,45 @@ public class CoreManager
var proc = await RunProcess(coreInfo, Global.CoreConfigFileName, displayLog, true, context.IsTunEnabled);
if (proc is null)
{
return;
return false;
}
_processService = proc;
return true;
}
private async Task CoreStartPreService(CoreConfigContext? preContext)
private async Task<bool> CoreStartPreService(CoreConfigContext? preContext)
{
if (_processService is { HasExited: false } && preContext != null)
if (preContext is null)
{
var preCoreType = preContext?.Node?.CoreType ?? ECoreType.sing_box;
var fileName = Utils.GetBinConfigPath(Global.CorePreConfigFileName);
var result = await CoreConfigHandler.GenerateClientConfig(preContext, fileName);
if (result.Success)
{
var coreInfo = CoreInfoManager.Instance.GetCoreInfo(preCoreType);
var proc = await RunProcess(coreInfo, Global.CorePreConfigFileName, true, true, preContext.IsTunEnabled);
if (proc is null)
{
return;
}
_processPreService = proc;
}
return true;
}
if (_processService is not { HasExited: false })
{
await UpdateFunc(true, ResUI.FailedToRunCore);
return false;
}
var preCoreType = preContext.Node?.CoreType ?? ECoreType.sing_box;
var fileName = Utils.GetBinConfigPath(Global.CorePreConfigFileName);
var result = await CoreConfigHandler.GenerateClientConfig(preContext, fileName);
if (!result.Success)
{
// Previously this result was ignored, so a missing/invalid
// configPre.json made Linux TUN fail without any actionable error.
await UpdateFunc(true, result.Msg ?? ResUI.FailedGenDefaultConfiguration);
return false;
}
var coreInfo = CoreInfoManager.Instance.GetCoreInfo(preCoreType);
var proc = await RunProcess(coreInfo, Global.CorePreConfigFileName, true, true, preContext.IsTunEnabled);
if (proc is null)
{
return false;
}
_processPreService = proc;
return true;
}
private async Task UpdateFunc(bool notify, string msg)
@@ -307,7 +333,7 @@ public class CoreManager
var fileName = CoreInfoManager.Instance.GetCoreExecFile(coreInfo, out var msg);
if (fileName.IsNullOrEmpty())
{
await UpdateFunc(false, msg);
await UpdateFunc(mayNeedSudo, msg);
return null;
}