Skip to content

Commit 77bb910

Browse files
committed
Auto-detect free-threaded libpython in venv home
PythonEnvironment.FindLibPythonInHome built a single candidate name from version.Major.Minor (e.g. libpython3.14.so) and missed the free-threaded variant (libpython3.14t.so / python314t.dll). pyvenv.cfg's version field doesn't distinguish the two builds, so probe both names and let File.Exists pick the one that's actually on disk. Unblocks the 3.14t CI jobs added in #2721: they were failing in PythonEngine.Initialize with "Py_IncRef: undefined symbol" because PythonDLL resolved to null and pythonnet fell back to dlopen of the dotnet binary itself.
1 parent c8e6154 commit 77bb910

1 file changed

Lines changed: 12 additions & 5 deletions

File tree

src/runtime/Util/PythonEnvironment.cs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,12 @@ private static Dictionary<string, string> TryParse(string venvCfg)
132132

133133
private static string? FindLibPythonInHome(string home, Version version)
134134
{
135-
var libPythonName = GetDefaultDllName(version);
135+
// Probe both — pyvenv.cfg's version field doesn't distinguish free-threaded.
136+
var libPythonNames = new[]
137+
{
138+
GetDefaultDllName(version),
139+
GetDefaultDllName(version, freeThreaded: true),
140+
};
136141

137142
List<string> pathsToCheck = new();
138143
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
@@ -155,7 +160,7 @@ private static Dictionary<string, string> TryParse(string venvCfg)
155160
}
156161

157162
return pathsToCheck
158-
.Select(path => Path.Combine(home, path, libPythonName))
163+
.SelectMany(path => libPythonNames.Select(name => Path.Combine(home, path, name)))
159164
.FirstOrDefault(File.Exists);
160165
}
161166

@@ -171,13 +176,15 @@ private static string ProgramNameFromPath(string path)
171176
}
172177
}
173178

174-
internal static string GetDefaultDllName(Version version)
179+
internal static string GetDefaultDllName(Version version, bool freeThreaded = false)
175180
{
176181
string prefix = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "" : "lib";
177182

183+
string ftSuffix = freeThreaded ? "t" : "";
184+
178185
string suffix = RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
179-
? Invariant($"{version.Major}{version.Minor}")
180-
: Invariant($"{version.Major}.{version.Minor}");
186+
? Invariant($"{version.Major}{version.Minor}{ftSuffix}")
187+
: Invariant($"{version.Major}.{version.Minor}{ftSuffix}");
181188

182189
string ext = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? ".dll"
183190
: RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? ".dylib"

0 commit comments

Comments
 (0)