adang1345 / delvewheel

Self-contained Python wheels for Windows
MIT License
116 stars 12 forks source link

OSError with "The operation completed successfully." #51

Closed njzjz closed 1 month ago

njzjz commented 1 month ago

We got this error message in the GitHub Actions (see log):

 tests\io\abinit\test_pseudos.py:11: in <module>
    from pymatgen.io.abinit.pseudos import Pseudo, PseudoTable
src\pymatgen\io\abinit\__init__.py:5: in <module>
    from .netcdf import (
src\pymatgen\io\abinit\netcdf.py:25: in <module>
    import netCDF4
C:\Users\runneradmin\micromamba\envs\pmg\lib\site-packages\netCDF4\__init__.py:28: in <module>
    _delvewheel_patch_1_7_0()
C:\Users\runneradmin\micromamba\envs\pmg\lib\site-packages\netCDF4\__init__.py:25: in _delvewheel_patch_1_7_0
    raise OSError('Error loading {}; {}'.format(lib, ctypes.FormatError(ctypes.get_last_error())))
E   OSError: Error loading charset-233f44715e5aacaf3a688c2faff5ddf7.dll; The operation completed successfully.

which is a piece of code in the netCDF4 package generated by delvewheel. https://github.com/adang1345/delvewheel/blob/e74686253154416dcba7c0cfd644f3b847bf267c/delvewheel/_wheel_repair.py#L73-L74

According to the Windows documentation, this error message means no error:

ERROR_SUCCESS 0 (0x0) The operation completed successfully.

So the error message does not make sense to me.

adang1345 commented 1 month ago

That's a strange error. Is this error intermittent? How frequently does it happen?

njzjz commented 1 month ago

Not very frequently, but I have seen this message several times. When searching on GitHub, I also see someone got the same error message in a different package: https://github.com/rdkit/rdkit/discussions/7072

adang1345 commented 1 month ago

I have found the cause of the error. Unless told otherwise, ctypes assumes that the return type of a function is a 32-bit C int. LoadLibraryExW() returns a 64-bit pointer to where the DLL is loaded. If the DLL happens to be loaded at an address that is a multiple of 0x100000000, then casting the address to a 32-bit C int results in the value 0. Python then sees a return value of 0 and thinks that the DLL failed to load. The problem is intermittent because the address at which the DLL is loaded is random.

The solution is to tell ctypes what the return type is.

janosh commented 1 month ago

thanks for the timely fix @adang1345! 👍