Skip to content

Commit

Permalink
Fix `OSError: Error loading *.dll; The operation completed successful…
Browse files Browse the repository at this point in the history
…ly.`

When LoadLibraryExW() is called from `ctypes`, the 64-bit void* return
value is cast to a 32-bit C int by default. If the base address of the
loaded DLL is a multiple of 2**32, then the lower 32 bits are 0, so
Python sees a return value of 0 and assumes that the DLL failed to load.
Set the return type properly so that the downcast is not done.

This fixes an intermittent issue with Python <= 3.7 or Conda Python <=
3.10 where an `OSError` is raised saying that a DLL failed to load but
also that the operation completed successfully.

Fix #51
  • Loading branch information
adang1345 committed Aug 7, 2024
1 parent f437a65 commit 151b7c9
Show file tree
Hide file tree
Showing 6 changed files with 97 additions and 0 deletions.
1 change: 1 addition & 0 deletions delvewheel/_wheel_repair.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ def _delvewheel_patch_{1}():
for lib in load_order:
lib_path = os.path.join(os.path.join(libs_dir, lib))
kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)
kernel32.LoadLibraryExW.restype = ctypes.c_void_p
if os.path.isfile(lib_path) and not kernel32.LoadLibraryExW(ctypes.c_wchar_p(lib_path), None, 0x00000008):
raise OSError('Error loading {{}}; {{}}'.format(lib, ctypes.FormatError(ctypes.get_last_error())))
Expand Down
14 changes: 14 additions & 0 deletions tests/run_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -1257,6 +1257,20 @@ def test_repair_iknowpy(self):
def test_needed(self):
check_call(['delvewheel', 'needed', 'simpleext/x64/simpledll.dll'])

def test_fixed_address(self):
"""Vendored DLL loads properly when base address is a multiple of
2**32. For this test, the address is 0x300000000."""
check_call(['delvewheel', 'repair', '--add-path', 'simpleext/x64/FixedAddress', 'simpleext/simpleext-0.0.1-0fixed-cp37-cp37m-win_amd64.whl'])
try:
check_call([sys.executable, '-m', 'pip', 'install', '--force-reinstall', 'wheelhouse/simpleext-0.0.1-0fixed-cp37-cp37m-win_amd64.whl'])
check_call([sys.executable, '-c', 'import simpleext.simpleext'])
finally:
try:
check_call([sys.executable, '-m', 'pip', 'uninstall', '-y', 'simpleext'])
except subprocess.CalledProcessError:
pass
remove('wheelhouse/simpleext-0.0.1-0fixed-cp37-cp37m-win_amd64.whl')


@unittest.skipUnless(sys.implementation.name == 'pypy', 'Python implementation is not PyPy')
class PyPyTestCase(unittest.TestCase):
Expand Down
6 changes: 6 additions & 0 deletions tests/simpleext/build/simpledll/simpledll.sln
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ Global
Release|x86 = Release|x86
ReleaseDLF|x64 = ReleaseDLF|x64
ReleaseDLF|x86 = ReleaseDLF|x86
ReleaseFixed|x64 = ReleaseFixed|x64
ReleaseFixed|x86 = ReleaseFixed|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{FF6B2276-D9EC-444D-AF0B-A736F8CC1E88}.Debug|x64.ActiveCfg = Debug|x64
Expand All @@ -27,6 +29,10 @@ Global
{FF6B2276-D9EC-444D-AF0B-A736F8CC1E88}.ReleaseDLF|x64.Build.0 = ReleaseDLF|x64
{FF6B2276-D9EC-444D-AF0B-A736F8CC1E88}.ReleaseDLF|x86.ActiveCfg = ReleaseDLF|Win32
{FF6B2276-D9EC-444D-AF0B-A736F8CC1E88}.ReleaseDLF|x86.Build.0 = ReleaseDLF|Win32
{FF6B2276-D9EC-444D-AF0B-A736F8CC1E88}.ReleaseFixed|x64.ActiveCfg = ReleaseFixed|x64
{FF6B2276-D9EC-444D-AF0B-A736F8CC1E88}.ReleaseFixed|x64.Build.0 = ReleaseFixed|x64
{FF6B2276-D9EC-444D-AF0B-A736F8CC1E88}.ReleaseFixed|x86.ActiveCfg = ReleaseFixed|Win32
{FF6B2276-D9EC-444D-AF0B-A736F8CC1E88}.ReleaseFixed|x86.Build.0 = ReleaseFixed|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
76 changes: 76 additions & 0 deletions tests/simpleext/build/simpledll/simpledll.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,14 @@
<Configuration>ReleaseDLF</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="ReleaseFixed|Win32">
<Configuration>ReleaseFixed</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="ReleaseFixed|x64">
<Configuration>ReleaseFixed</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
Expand Down Expand Up @@ -47,6 +55,13 @@
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseFixed|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseDLF|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
Expand All @@ -67,6 +82,13 @@
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseFixed|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseDLF|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
Expand All @@ -85,6 +107,9 @@
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseFixed|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseDLF|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
Expand All @@ -94,6 +119,9 @@
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseFixed|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseDLF|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
Expand All @@ -106,6 +134,10 @@
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(ShortProjectName)\$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseFixed|Win32'">
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(ShortProjectName)\$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseDLF|Win32'">
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(ShortProjectName)\$(Platform)\$(Configuration)\</IntDir>
Expand Down Expand Up @@ -144,6 +176,28 @@
<EnableUAC>false</EnableUAC>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseFixed|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;SIMPLEDLL_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
<BaseAddress>0x20000000</BaseAddress>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<FixedBaseAddress>true</FixedBaseAddress>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseDLF|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
Expand Down Expand Up @@ -198,6 +252,28 @@
<EnableUAC>false</EnableUAC>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseFixed|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;SIMPLEDLL_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
<BaseAddress>0x300000000</BaseAddress>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<FixedBaseAddress>true</FixedBaseAddress>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseDLF|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
Expand Down
Binary file not shown.
Binary file added tests/simpleext/x64/FixedAddress/simpledll.dll
Binary file not shown.

0 comments on commit 151b7c9

Please sign in to comment.