Closed StarHeartHunt closed 1 month ago
The wheels for etcpak are compiled with simd instructions that most newer CPUs support. As your cpu is pretty dated, it doesn't support some of these, resulting in the illegal instruction error.
For now you can simply install etcpak "from source" instead of from pip, which should solve the problem.
pip install git+https://github.com/K0lb3/etcpak
I don't really want to serve etcpak precompiled without simd instructions, as the wrapped C-library makes heavy use of them to improve the performance by a lot. One thing I could try would be bundling two c-extensions into etcpak, one with simd and one without simd instructions, with the init.py selecting which one to import at runtime.
https://pypi.org/project/cpufeature/ should probably do, just that I have to bake it into etcpak as well
@StarHeartHunt can you check if the problem persists with the current version of etcpak?
Granted, I guess that it does, given that you showed that the problem doesn't occur on import, which happens on Windows. I guess that I might have to add cpufeature as dependency for Linux (and Mac), which checks before import if simd would work.
@StarHeartHunt can you check if the problem persists with the current version of etcpak?
Granted, I guess that it does, given that you showed that the problem doesn't occur on import, which happens on Windows. I guess that I might have to add cpufeature as dependency for Linux (and Mac), which checks before import if simd would work.
🤔still got Illegal instruction (core dumped)
when import UnityPy / etcpak on Linux using etcpak v0.9.10
root@0eccc519576c:/app# python
Python 3.11.10 (main, Sep 12 2024, 21:11:07) [GCC 12.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import UnityPy
Illegal instruction (core dumped)
>>> import etcpak
Illegal instruction (core dumped)
and gdb output
Starting program: /usr/local/bin/python -c import\ UnityPy
warning: Error disabling address space randomization: Operation not permitted
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Program received signal SIGILL, Illegal instruction.
0x00007fa2e696418d in Color::XYZ::XYZ (this=0x7fa2e69941a0 <Color::white>, rgb=...) at src/etcpak/ColorSpace.cpp:31
After deleting the import error catch (only try to import no simd build) on my machine, it seems that the no simd binary build is valid. Since it will crash and no ImportError is raised when importing simd binary build while simd feature is unavailable, maybe using cpufeature
to check simd feature support would be a better solution?
>>> import etcpak
>>> etcpak.__name__
'etcpak'
>>> etcpak.compress_to_etc2_alpha
<function compress_to_etc2_alpha at 0x7f73dd8274c0>
@StarHeartHunt I build cpufeature into etcpak now, as cpufeature itself doesn't ship any python 3.12 and 3.13 binaries. When importing the simd version, it checks if the cpu supports all simd features selected at compile time, and if not, causes an import error, and uses the no simd version.
The wheels for that are already up, so it would be great if you could check if they work now.
@StarHeartHunt I build cpufeature into etcpak now, as cpufeature itself doesn't ship any python 3.12 and 3.13 binaries. When importing the simd version, it checks if the cpu supports all simd features selected at compile time, and if not, causes an import error, and uses the no simd version.
The wheels for that are already up, so it would be great if you could check if they work now.
Tested etcpak 0.9.11, still got Illegal instruction (core dumped)
root@27bdd4c8a9c9:/app# python -c "import etcpak"
Illegal instruction (core dumped)
pip list result:
root@27bdd4c8a9c9:/app# python -m pip list
Package Version
----------------- -----------
annotated-types 0.7.0
anyio 4.4.0
APScheduler 3.10.4
Brotli 1.1.0
bson 0.5.10
certifi 2024.8.30
click 8.1.7
etcpak 0.9.11
fastapi 0.115.0
fsspec 2024.9.0
h11 0.14.0
httpcore 1.0.5
httptools 0.6.1
httpx 0.27.2
idna 3.10
loguru 0.7.2
lz4 4.3.3
pillow 10.4.0
pip 24.0
pycryptodome 3.20.0
pydantic 2.9.2
pydantic_core 2.23.4
pydantic-settings 2.5.2
pydub 0.25.1
pyfmodex 0.7.2
python-dateutil 2.9.0.post0
python-dotenv 1.0.1
pytz 2024.2
PyYAML 6.0.2
sentry-sdk 2.14.0
setuptools 65.5.1
six 1.16.0
sniffio 1.3.1
starlette 0.38.5
tabulate 0.9.0
tenacity 9.0.0
texture2ddecoder 1.0.4
typing_extensions 4.12.2
tzlocal 5.2
UnityPy 1.10.18
urllib3 2.2.3
uvicorn 0.30.6
uvloop 0.20.0
watchfiles 0.24.0
websockets 13.0.1
wheel 0.44.0
After a little digging into the binary lib, i found that there are two global instances in ColorSpace.cpp, which will cause initialization calls in the .init_array
segment, and .init_array
will be called on library loading (dl_open). That's why the cpufeature check has no effect since it's entrypoint is PyInit__etcpak_simd
.
gdb stacktrace:
#2 0x00007f84e9a5633d in Color::XYZ::XYZ (this=0x7f84e9a871c0 <Color::white>, rgb=...) at src/etcpak/ColorSpace.cpp:31
#3 0x00007f84e9a48ced in __static_initialization_and_destruction_0 (__initialize_p=1, __priority=65535) at src/etcpak/ColorSpace.cpp:10
#4 _GLOBAL__sub_I_ColorSpace.cpp(void) () at src/etcpak/ColorSpace.cpp:114
#5 0x00007f84ea5419ce in call_init (env=0x7fff3407e538, argv=0x7fff3407e518, argc=3, l=<optimized out>) at ./elf/dl-init.c:74
#6 call_init (l=<optimized out>, argc=3, argv=0x7fff3407e518, env=0x7fff3407e538) at ./elf/dl-init.c:26
#7 0x00007f84ea541ab4 in _dl_init (main_map=0x5643aceecf50, argc=3, argv=0x7fff3407e518, env=0x7fff3407e538) at ./elf/dl-init.c:121
#8 0x00007f84e9f7b024 in __GI__dl_catch_exception (exception=<optimized out>, operate=<optimized out>, args=<optimized out>) at ./elf/dl-error-skeleton.c:182
#9 0x00007f84ea54821e in dl_open_worker (a=a@entry=0x7fff3407cf80) at ./elf/dl-open.c:808
#10 0x00007f84e9f7afca in __GI__dl_catch_exception (exception=<optimized out>, operate=<optimized out>, args=<optimized out>) at ./elf/dl-error-skeleton.c:208
#11 0x00007f84ea5485b8 in _dl_open (file=0x7f84e9c86350 "/usr/local/lib/python3.11/site-packages/etcpak/_etcpak_simd.cpython-311-x86_64-linux-gnu.so", mode=<optimized out>, caller_dlopen=0x7f84ea2b2dd1,
nsid=<optimized out>, argc=3, argv=0x7fff3407e518, env=0x7fff3407e538) at ./elf/dl-open.c:884
#12 0x00007f84e9eb1438 in dlopen_doit (a=a@entry=0x7fff3407d1f0) at ./dlfcn/dlopen.c:56
#13 0x00007f84e9f7afca in __GI__dl_catch_exception (exception=exception@entry=0x7fff3407d150, operate=<optimized out>, args=<optimized out>) at ./elf/dl-error-skeleton.c:208
#14 0x00007f84e9f7b07f in __GI__dl_catch_error (objname=0x7fff3407d1a8, errstring=0x7fff3407d1b0, mallocedp=0x7fff3407d1a7, operate=<optimized out>, args=<optimized out>) at ./elf/dl-error-skeleton.c:227
#15 0x00007f84e9eb0f27 in _dlerror_run (operate=operate@entry=0x7f84e9eb13e0 <dlopen_doit>, args=args@entry=0x7fff3407d1f0) at ./dlfcn/dlerror.c:138
#16 0x00007f84e9eb14e9 in dlopen_implementation (dl_caller=<optimized out>, mode=<optimized out>, file=<optimized out>) at ./dlfcn/dlopen.c:71
#17 ___dlopen (file=<optimized out>, mode=<optimized out>) at ./dlfcn/dlopen.c:81
#18 0x00007f84ea2b2dd1 in ?? () from /usr/local/bin/../lib/libpython3.11.so.1.0
#19 0x00007f84ea2b2a0c in ?? () from /usr/local/bin/../lib/libpython3.11.so.1.0
And the simd optimization seems to be applied on the cpufeature check part, which will also cause SIGILL crash:
(gdb) call check_cpu_features()
Program received signal SIGILL, Illegal instruction.
0x00007f84e9a4920b in check_cpu_features () at src/check_cpufeatures.cpp:69
warning: Source file is more recent than executable.
69 if ((info[1] & ((int)1 << 5)) == 0)
I see, thanks, that helps a lot.
I'm a bit confused as to why the cpu feature check causes a crash as well, especially the given line.
So I guess that the cpu check has to come before the simd import, and isn't supposed to contain any simd functions either.
....I probably should try to setup a qemu without simd support to find a working solution.
I moved the check_cpufeature functionality into a separate extension now, which should fix the issue of simd instructions being called directly on import.
I moved the check_cpufeature functionality into a separate extension now, which should fix the issue of simd instructions being called directly on import.
It works with 0.9.12 now, thanks!
Thanks for the feedback, great to hear that this is finally solved for good.
I will also use it as solution for some other repos likes astc-encoder I'm going to wrap, so it's perfect that this is sorted out.
Code
Error Illegal instruction (core dumped)
with gdb attached:
Bug no error occurred on import
To Reproduce