I've tried virtualizing /usr/local/lib/python* with wasi-virt so wasi python can find site-packages
the example runs if I don't use wasi-virt but provide wasmtime preopened dirs, I'm pretty sure wasi-virt just doesn't provide some method python uses to guess encodings.
with wasi-virt, python fails during initialization (Fatal Python error: init_fs_encoding: failed to get the Python codec of the filesystem encoding
)
I can confirm with std::fs that the files are readable, any directions how I can debug this further?
If you haven't already, make sure the PYTHONHOME and PYTHONPATH environment variables are set correctly in the guest, i.e. that they're pointing to the guest directory where the CPython system files reside.
what should PYTHONPATH be if there is no python executable?
but I should print those two variables to see what they are set to in the happy path with preopen
(I didn't set them in either version)
This is how componentize-py
sets up directories and env variables during pre-initialization, FWIW: https://github.com/bytecodealliance/componentize-py/blob/243c4bf62a5a4286e261c10e4cb2897b16c3b3dd/src/lib.rs#L163-L390. Note that python-lib.tar.zst
is created from the lib/python3.11 directory here: https://github.com/bytecodealliance/componentize-py/blob/243c4bf62a5a4286e261c10e4cb2897b16c3b3dd/build.rs#L173-L186
(got distracted by work) that is the part that works for both of us, wasictx with preopened dirs is how I currently run my python components, but when I use no preopened_dirs and instead pre-bundle the component with wasi-virt, I can read the python files but I get the same error you would see if you comment out your preopened_dir calls
with "i can read the files" I mean std::fs::read gives me the expected data but there must be something else python expects during init_fs_encoding
Strange. Maybe there's a bug in wasi-virt
related to e.g. stat
ing files
I have to reduce the example to something manageable and then I'll see if some form of debugging can find out what exactly python tries to do
@Ramon Klass if you're able to share any test binary at all I'd be happy to look into it
that, uh, took longer than expected
@Guy Bedford https://github.com/Gentle/repro-wasi-virt-python
build.sh does all the steps to run the good and the sad example
(I do not know how to write or run command components so I made a simple host for a reactor)
thank you @Ramon Klass will take a look soon
@Ramon Klass just tried this example but I get:
Error: Unable to compose virtualized adapter into component.
Make sure virtualizations are enabled and being used.
Caused by:
0: failed to connect instance `$input` to definition component `/var/folders/m4/hc32lfnd57d208n1w_v_5nvw0000gp/T/virt.1696971376.wasm`
1: source instance export `wasi:io/streams` is not compatible with target instance import `wasi:io/streams`
so it seems like we're hitting the wit version mismatch stuff
is there some way I can lock to the same version you're using?
alternatively if you can somehow point me to the wit version being used to generate your component / if we can figure out an upgrade path in wasi virt that can work for both
wasi-virt now has the problem itself that wasm-compose doesn't support resources so we will be stuck to the version just prior
hm I've used the release version of wasm-tools and a current version of wasi-virt cargo installed from git and the wit-bindgen revision is in Cargo.lock
and 13.0.0 wasi_snapshot_preview1.reactor.wasm
either way that's not the error I expected
ahh, I was able to replicate it with the global wasi-virt install updated, thanks for clarifying
:) I hope it helps
@Ramon Klass I created a debugging build for Wasi-VIRT in https://github.com/bytecodealliance/WASI-Virt/pull/23
Using this debug build against your replication then gives the following output:
CALL wasi:filesystem/types#get_type
CALL wasi:io/streams#blocking_write_and_flush
OK1
CALL wasi:filesystem/types#stat_at FD=0 PATH=local/lib/python3.11/os.py
CALL wasi:filesystem/types#metadata_hash_at
CALL wasi:filesystem/types#stat_at FD=0 PATH=local/lib/python3.11/lib-dynload
CALL wasi:filesystem/types#metadata_hash_at
CALL wasi:filesystem/types#stat_at FD=0 PATH=local/lib/python311.zip
CALL wasi:filesystem/types#metadata_hash_at
CALL wasi:filesystem/types#get_flags
CALL wasi:filesystem/types#get_type
CALL wasi:filesystem/types#open_at
CALL wasi:filesystem/types#get_type
CALL wasi:filesystem/types#stat FD=1
CALL wasi:filesystem/types#metadata_hash
CALL wasi:filesystem/types#get_flags
CALL wasi:filesystem/types#get_type
CALL wasi:filesystem/types#stat FD=1
CALL wasi:filesystem/types#read_via_stream
CALL wasi:filesystem/types#drop_descriptor
CALL wasi:filesystem/types#stat_at FD=0 PATH=local/lib/python311.zip
CALL wasi:filesystem/types#metadata_hash_at
CALL wasi:filesystem/types#stat_at FD=0 PATH=local/lib/python3.11
CALL wasi:filesystem/types#metadata_hash_at
CALL wasi:filesystem/types#stat_at FD=0 PATH=local/lib/python3.11
CALL wasi:filesystem/types#metadata_hash_at
CALL wasi:filesystem/types#stat_at FD=0 PATH=local/lib/python3.11
CALL wasi:filesystem/types#metadata_hash_at
CALL wasi:filesystem/types#get_flags
CALL wasi:filesystem/types#get_type
CALL wasi:filesystem/types#open_at
CALL wasi:filesystem/types#get_type
CALL wasi:filesystem/types#read_directory
CALL wasi:filesystem/types#metadata_hash
CALL wasi:filesystem/types#read_directory_entry
CALL wasi:filesystem/types#metadata_hash_at
CALL wasi:filesystem/types#read_directory_entry
CALL wasi:filesystem/types#metadata_hash_at
CALL wasi:filesystem/types#read_directory_entry
CALL wasi:filesystem/types#drop_directory_entry_stream
CALL wasi:filesystem/types#stat_at FD=2 PATH=.
CALL wasi:filesystem/types#stat_at FD=2 PATH=lib-dynload
CALL wasi:filesystem/types#metadata_hash_at
CALL wasi:filesystem/types#stat_at FD=2 PATH=os.py
CALL wasi:filesystem/types#metadata_hash_at
CALL wasi:filesystem/types#drop_descriptor
CALL wasi:filesystem/types#stat_at FD=0 PATH=local/lib/python3.11/lib-dynload
CALL wasi:filesystem/types#metadata_hash_at
CALL wasi:filesystem/types#stat_at FD=0 PATH=local/lib/python3.11/lib-dynload
CALL wasi:filesystem/types#metadata_hash_at
CALL wasi:filesystem/types#stat_at FD=0 PATH=local/lib/python3.11/lib-dynload
CALL wasi:filesystem/types#metadata_hash_at
CALL wasi:filesystem/types#get_flags
CALL wasi:filesystem/types#get_type
CALL wasi:filesystem/types#open_at
CALL wasi:filesystem/types#get_type
CALL wasi:filesystem/types#read_directory
CALL wasi:filesystem/types#metadata_hash
CALL wasi:filesystem/types#read_directory_entry
CALL wasi:filesystem/types#metadata_hash_at
CALL wasi:filesystem/types#read_directory_entry
CALL wasi:filesystem/types#drop_directory_entry_stream
CALL wasi:filesystem/types#stat_at FD=3 PATH=.
CALL wasi:filesystem/types#stat_at FD=3 PATH=.empty
CALL wasi:filesystem/types#metadata_hash_at
CALL wasi:filesystem/types#drop_descriptor
CALL wasi:io/streams#blocking_write_and_flush
Python path configuration:
CALL wasi:io/streams#blocking_write_and_flush
PYTHONHOME = CALL wasi:io/streams#blocking_write_and_flush
(not set)CALL wasi:io/streams#blocking_write_and_flush
CALL wasi:io/streams#blocking_write_and_flush
PYTHONPATH = CALL wasi:io/streams#blocking_write_and_flush
(not set)CALL wasi:io/streams#blocking_write_and_flush
CALL wasi:io/streams#blocking_write_and_flush
program name = CALL wasi:io/streams#blocking_write_and_flush
'CALL wasi:io/streams#blocking_write_and_flush
pCALL wasi:io/streams#blocking_write_and_flush
yCALL wasi:io/streams#blocking_write_and_flush
tCALL wasi:io/streams#blocking_write_and_flush
hCALL wasi:io/streams#blocking_write_and_flush
oCALL wasi:io/streams#blocking_write_and_flush
nCALL wasi:io/streams#blocking_write_and_flush
3CALL wasi:io/streams#blocking_write_and_flush
'CALL wasi:io/streams#blocking_write_and_flush
CALL wasi:io/streams#blocking_write_and_flush
isolated = 0
CALL wasi:io/streams#blocking_write_and_flush
environment = 1
CALL wasi:io/streams#blocking_write_and_flush
user site = 1
CALL wasi:io/streams#blocking_write_and_flush
safe_path = 0
CALL wasi:io/streams#blocking_write_and_flush
import site = 1
CALL wasi:io/streams#blocking_write_and_flush
is in build tree = 0
CALL wasi:io/streams#blocking_write_and_flush
stdlib dir = CALL wasi:io/streams#blocking_write_and_flush
'CALL wasi:io/streams#blocking_write_and_flush
/CALL wasi:io/streams#blocking_write_and_flush
uCALL wasi:io/streams#blocking_write_and_flush
sCALL wasi:io/streams#blocking_write_and_flush
rCALL wasi:io/streams#blocking_write_and_flush
/CALL wasi:io/streams#blocking_write_and_flush
lCALL wasi:io/streams#blocking_write_and_flush
oCALL wasi:io/streams#blocking_write_and_flush
cCALL wasi:io/streams#blocking_write_and_flush
aCALL wasi:io/streams#blocking_write_and_flush
lCALL wasi:io/streams#blocking_write_and_flush
/CALL wasi:io/streams#blocking_write_and_flush
lCALL wasi:io/streams#blocking_write_and_flush
iCALL wasi:io/streams#blocking_write_and_flush
bCALL wasi:io/streams#blocking_write_and_flush
/CALL wasi:io/streams#blocking_write_and_flush
pCALL wasi:io/streams#blocking_write_and_flush
yCALL wasi:io/streams#blocking_write_and_flush
tCALL wasi:io/streams#blocking_write_and_flush
hCALL wasi:io/streams#blocking_write_and_flush
oCALL wasi:io/streams#blocking_write_and_flush
nCALL wasi:io/streams#blocking_write_and_flush
3CALL wasi:io/streams#blocking_write_and_flush
.CALL wasi:io/streams#blocking_write_and_flush
1CALL wasi:io/streams#blocking_write_and_flush
1CALL wasi:io/streams#blocking_write_and_flush
'CALL wasi:io/streams#blocking_write_and_flush
CALL wasi:io/streams#blocking_write_and_flush
sys._base_executable = CALL wasi:io/streams#blocking_write_and_flush
''CALL wasi:io/streams#blocking_write_and_flush
CALL wasi:io/streams#blocking_write_and_flush
sys.base_prefix = CALL wasi:io/streams#blocking_write_and_flush
'/usr/local'CALL wasi:io/streams#blocking_write_and_flush
CALL wasi:io/streams#blocking_write_and_flush
sys.base_exec_prefix = CALL wasi:io/streams#blocking_write_and_flush
'/usr/local'CALL wasi:io/streams#blocking_write_and_flush
CALL wasi:io/streams#blocking_write_and_flush
sys.platlibdir = CALL wasi:io/streams#blocking_write_and_flush
'lib'CALL wasi:io/streams#blocking_write_and_flush
CALL wasi:io/streams#blocking_write_and_flush
sys.executable = CALL wasi:io/streams#blocking_write_and_flush
''CALL wasi:io/streams#blocking_write_and_flush
CALL wasi:io/streams#blocking_write_and_flush
sys.prefix = CALL wasi:io/streams#blocking_write_and_flush
'/usr/local'CALL wasi:io/streams#blocking_write_and_flush
CALL wasi:io/streams#blocking_write_and_flush
sys.exec_prefix = CALL wasi:io/streams#blocking_write_and_flush
'/usr/local'CALL wasi:io/streams#blocking_write_and_flush
CALL wasi:io/streams#blocking_write_and_flush
sys.path = [
CALL wasi:io/streams#blocking_write_and_flush
'/usr/local/lib/python311.zip',
CALL wasi:io/streams#blocking_write_and_flush
'/usr/local/lib/python3.11',
CALL wasi:io/streams#blocking_write_and_flush
'/usr/local/lib/python3.11/lib-dynload',
CALL wasi:io/streams#blocking_write_and_flush
]
CALL wasi:io/streams#blocking_write_and_flush
Fatal Python error: CALL wasi:io/streams#blocking_write_and_flush
init_fs_encodingCALL wasi:io/streams#blocking_write_and_flush
: CALL wasi:io/streams#blocking_write_and_flush
failed to get the Python codec of the filesystem encodingCALL wasi:io/streams#blocking_write_and_flush
CALL wasi:io/streams#blocking_write_and_flush
Python runtime state: CALL wasi:io/streams#blocking_write_and_flush
core initializedCALL wasi:io/streams#blocking_write_and_flush
CALL wasi:io/streams#blocking_write_and_flush
ModuleNotFoundErrorCALL wasi:io/streams#blocking_write_and_flush
: CALL wasi:io/streams#blocking_write_and_flush
No module named 'encodings'CALL wasi:io/streams#blocking_write_and_flush
CALL wasi:io/streams#blocking_write_and_flush
CALL wasi:io/streams#blocking_write_and_flush
Current thread 0xCALL wasi:io/streams#blocking_write_and_flush
00000000CALL wasi:io/streams#blocking_write_and_flush
(most recent call first):
CALL wasi:io/streams#blocking_write_and_flush
<no Python frame>
Without knowing the details of the Python error further it is difficult to tell where the issue is
but I hope that at least helps to start to narrow it down further
@Joel Dice if you say this might be a stat issue - note that virtualied files in Wasi VIRT currently return times that are at the epoch
not sure if that would affect things
and here's a version with even more argument context included:
CALL wasi:filesystem/types#get_type FD=0
CALL wasi:io/streams#blocking_write_and_flush SID=1
OK1
CALL wasi:filesystem/types#stat_at FD=0 PATH=local/lib/python3.11/os.py
CALL wasi:filesystem/types#metadata_hash_at FD=0 PATH=local/lib/python3.11/os.py
CALL wasi:filesystem/types#stat_at FD=0 PATH=local/lib/python3.11/lib-dynload
CALL wasi:filesystem/types#metadata_hash_at FD=0 PATH=local/lib/python3.11/lib-dynload
CALL wasi:filesystem/types#stat_at FD=0 PATH=local/lib/python311.zip
CALL wasi:filesystem/types#metadata_hash_at FD=0 PATH=local/lib/python311.zip
CALL wasi:filesystem/types#get_flags FD=0
CALL wasi:filesystem/types#get_type FD=0
CALL wasi:filesystem/types#open_at FD=0 PATH=local/lib/python311.zip
CALL wasi:filesystem/types#get_type FD=1
CALL wasi:filesystem/types#stat FD=1
CALL wasi:filesystem/types#metadata_hash FD=1
CALL wasi:filesystem/types#get_flags FD=1
CALL wasi:filesystem/types#get_type FD=1
CALL wasi:filesystem/types#stat FD=1
CALL wasi:filesystem/types#read_via_stream FD=1 OFFSET=4107234
CALL wasi:filesystem/types#drop_descriptor FD=1
CALL wasi:filesystem/types#stat_at FD=0 PATH=local/lib/python311.zip
CALL wasi:filesystem/types#metadata_hash_at FD=0 PATH=local/lib/python311.zip
CALL wasi:filesystem/types#stat_at FD=0 PATH=local/lib/python3.11
CALL wasi:filesystem/types#metadata_hash_at FD=0 PATH=local/lib/python3.11
CALL wasi:filesystem/types#stat_at FD=0 PATH=local/lib/python3.11
CALL wasi:filesystem/types#metadata_hash_at FD=0 PATH=local/lib/python3.11
CALL wasi:filesystem/types#stat_at FD=0 PATH=local/lib/python3.11
CALL wasi:filesystem/types#metadata_hash_at FD=0 PATH=local/lib/python3.11
CALL wasi:filesystem/types#get_flags FD=0
CALL wasi:filesystem/types#get_type FD=0
CALL wasi:filesystem/types#open_at FD=0 PATH=local/lib/python3.11
CALL wasi:filesystem/types#get_type FD=2
CALL wasi:filesystem/types#read_directory FD=2
CALL wasi:filesystem/types#metadata_hash FD=2
CALL wasi:filesystem/types#read_directory_entry SID=3
CALL wasi:filesystem/types#metadata_hash_at FD=2 PATH=lib-dynload
CALL wasi:filesystem/types#read_directory_entry SID=3
CALL wasi:filesystem/types#metadata_hash_at FD=2 PATH=os.py
CALL wasi:filesystem/types#read_directory_entry SID=3
CALL wasi:filesystem/types#drop_directory_entry_stream SID=3
CALL wasi:filesystem/types#stat_at FD=2 PATH=.
CALL wasi:filesystem/types#stat_at FD=2 PATH=lib-dynload
CALL wasi:filesystem/types#metadata_hash_at FD=2 PATH=lib-dynload
CALL wasi:filesystem/types#stat_at FD=2 PATH=os.py
CALL wasi:filesystem/types#metadata_hash_at FD=2 PATH=os.py
CALL wasi:filesystem/types#drop_descriptor FD=2
CALL wasi:filesystem/types#stat_at FD=0 PATH=local/lib/python3.11/lib-dynload
CALL wasi:filesystem/types#metadata_hash_at FD=0 PATH=local/lib/python3.11/lib-dynload
CALL wasi:filesystem/types#stat_at FD=0 PATH=local/lib/python3.11/lib-dynload
CALL wasi:filesystem/types#metadata_hash_at FD=0 PATH=local/lib/python3.11/lib-dynload
CALL wasi:filesystem/types#stat_at FD=0 PATH=local/lib/python3.11/lib-dynload
CALL wasi:filesystem/types#metadata_hash_at FD=0 PATH=local/lib/python3.11/lib-dynload
CALL wasi:filesystem/types#get_flags FD=0
CALL wasi:filesystem/types#get_type FD=0
CALL wasi:filesystem/types#open_at FD=0 PATH=local/lib/python3.11/lib-dynload
CALL wasi:filesystem/types#get_type FD=3
CALL wasi:filesystem/types#read_directory FD=3
CALL wasi:filesystem/types#metadata_hash FD=3
CALL wasi:filesystem/types#read_directory_entry SID=4
CALL wasi:filesystem/types#metadata_hash_at FD=3 PATH=.empty
CALL wasi:filesystem/types#read_directory_entry SID=4
CALL wasi:filesystem/types#drop_directory_entry_stream SID=4
CALL wasi:filesystem/types#stat_at FD=3 PATH=.
CALL wasi:filesystem/types#stat_at FD=3 PATH=.empty
CALL wasi:filesystem/types#metadata_hash_at FD=3 PATH=.empty
CALL wasi:filesystem/types#drop_descriptor FD=3
CALL wasi:io/streams#blocking_write_and_flush SID=2
Python path configuration:
CALL wasi:io/streams#blocking_write_and_flush SID=2
PYTHONHOME = CALL wasi:io/streams#blocking_write_and_flush SID=2
(not set)CALL wasi:io/streams#blocking_write_and_flush SID=2
CALL wasi:io/streams#blocking_write_and_flush SID=2
PYTHONPATH = CALL wasi:io/streams#blocking_write_and_flush SID=2
(not set)CALL wasi:io/streams#blocking_write_and_flush SID=2
CALL wasi:io/streams#blocking_write_and_flush SID=2
program name = CALL wasi:io/streams#blocking_write_and_flush SID=2
'CALL wasi:io/streams#blocking_write_and_flush SID=2
pCALL wasi:io/streams#blocking_write_and_flush SID=2
yCALL wasi:io/streams#blocking_write_and_flush SID=2
tCALL wasi:io/streams#blocking_write_and_flush SID=2
hCALL wasi:io/streams#blocking_write_and_flush SID=2
oCALL wasi:io/streams#blocking_write_and_flush SID=2
nCALL wasi:io/streams#blocking_write_and_flush SID=2
3CALL wasi:io/streams#blocking_write_and_flush SID=2
'CALL wasi:io/streams#blocking_write_and_flush SID=2
CALL wasi:io/streams#blocking_write_and_flush SID=2
isolated = 0
CALL wasi:io/streams#blocking_write_and_flush SID=2
environment = 1
CALL wasi:io/streams#blocking_write_and_flush SID=2
user site = 1
CALL wasi:io/streams#blocking_write_and_flush SID=2
safe_path = 0
CALL wasi:io/streams#blocking_write_and_flush SID=2
import site = 1
CALL wasi:io/streams#blocking_write_and_flush SID=2
is in build tree = 0
CALL wasi:io/streams#blocking_write_and_flush SID=2
stdlib dir = CALL wasi:io/streams#blocking_write_and_flush SID=2
'CALL wasi:io/streams#blocking_write_and_flush SID=2
/CALL wasi:io/streams#blocking_write_and_flush SID=2
uCALL wasi:io/streams#blocking_write_and_flush SID=2
sCALL wasi:io/streams#blocking_write_and_flush SID=2
rCALL wasi:io/streams#blocking_write_and_flush SID=2
/CALL wasi:io/streams#blocking_write_and_flush SID=2
lCALL wasi:io/streams#blocking_write_and_flush SID=2
oCALL wasi:io/streams#blocking_write_and_flush SID=2
cCALL wasi:io/streams#blocking_write_and_flush SID=2
aCALL wasi:io/streams#blocking_write_and_flush SID=2
lCALL wasi:io/streams#blocking_write_and_flush SID=2
/CALL wasi:io/streams#blocking_write_and_flush SID=2
lCALL wasi:io/streams#blocking_write_and_flush SID=2
iCALL wasi:io/streams#blocking_write_and_flush SID=2
bCALL wasi:io/streams#blocking_write_and_flush SID=2
/CALL wasi:io/streams#blocking_write_and_flush SID=2
pCALL wasi:io/streams#blocking_write_and_flush SID=2
yCALL wasi:io/streams#blocking_write_and_flush SID=2
tCALL wasi:io/streams#blocking_write_and_flush SID=2
hCALL wasi:io/streams#blocking_write_and_flush SID=2
oCALL wasi:io/streams#blocking_write_and_flush SID=2
nCALL wasi:io/streams#blocking_write_and_flush SID=2
3CALL wasi:io/streams#blocking_write_and_flush SID=2
.CALL wasi:io/streams#blocking_write_and_flush SID=2
1CALL wasi:io/streams#blocking_write_and_flush SID=2
1CALL wasi:io/streams#blocking_write_and_flush SID=2
'CALL wasi:io/streams#blocking_write_and_flush SID=2
CALL wasi:io/streams#blocking_write_and_flush SID=2
sys._base_executable = CALL wasi:io/streams#blocking_write_and_flush SID=2
''CALL wasi:io/streams#blocking_write_and_flush SID=2
CALL wasi:io/streams#blocking_write_and_flush SID=2
sys.base_prefix = CALL wasi:io/streams#blocking_write_and_flush SID=2
'/usr/local'CALL wasi:io/streams#blocking_write_and_flush SID=2
CALL wasi:io/streams#blocking_write_and_flush SID=2
sys.base_exec_prefix = CALL wasi:io/streams#blocking_write_and_flush SID=2
'/usr/local'CALL wasi:io/streams#blocking_write_and_flush SID=2
CALL wasi:io/streams#blocking_write_and_flush SID=2
sys.platlibdir = CALL wasi:io/streams#blocking_write_and_flush SID=2
'lib'CALL wasi:io/streams#blocking_write_and_flush SID=2
CALL wasi:io/streams#blocking_write_and_flush SID=2
sys.executable = CALL wasi:io/streams#blocking_write_and_flush SID=2
''CALL wasi:io/streams#blocking_write_and_flush SID=2
CALL wasi:io/streams#blocking_write_and_flush SID=2
sys.prefix = CALL wasi:io/streams#blocking_write_and_flush SID=2
'/usr/local'CALL wasi:io/streams#blocking_write_and_flush SID=2
CALL wasi:io/streams#blocking_write_and_flush SID=2
sys.exec_prefix = CALL wasi:io/streams#blocking_write_and_flush SID=2
'/usr/local'CALL wasi:io/streams#blocking_write_and_flush SID=2
CALL wasi:io/streams#blocking_write_and_flush SID=2
sys.path = [
CALL wasi:io/streams#blocking_write_and_flush SID=2
'/usr/local/lib/python311.zip',
CALL wasi:io/streams#blocking_write_and_flush SID=2
'/usr/local/lib/python3.11',
CALL wasi:io/streams#blocking_write_and_flush SID=2
'/usr/local/lib/python3.11/lib-dynload',
CALL wasi:io/streams#blocking_write_and_flush SID=2
]
CALL wasi:io/streams#blocking_write_and_flush SID=2
Fatal Python error: CALL wasi:io/streams#blocking_write_and_flush SID=2
init_fs_encodingCALL wasi:io/streams#blocking_write_and_flush SID=2
: CALL wasi:io/streams#blocking_write_and_flush SID=2
failed to get the Python codec of the filesystem encodingCALL wasi:io/streams#blocking_write_and_flush SID=2
CALL wasi:io/streams#blocking_write_and_flush SID=2
Python runtime state: CALL wasi:io/streams#blocking_write_and_flush SID=2
core initializedCALL wasi:io/streams#blocking_write_and_flush SID=2
CALL wasi:io/streams#blocking_write_and_flush SID=2
ModuleNotFoundErrorCALL wasi:io/streams#blocking_write_and_flush SID=2
: CALL wasi:io/streams#blocking_write_and_flush SID=2
No module named 'encodings'CALL wasi:io/streams#blocking_write_and_flush SID=2
CALL wasi:io/streams#blocking_write_and_flush SID=2
CALL wasi:io/streams#blocking_write_and_flush SID=2
Current thread 0xCALL wasi:io/streams#blocking_write_and_flush SID=2
00000000CALL wasi:io/streams#blocking_write_and_flush SID=2
(most recent call first):
CALL wasi:io/streams#blocking_write_and_flush SID=2
<no Python frame>
Am I reading correctly that the guest only ever seems to stat
with a path that starts with local/
? It never seems to look at the /usr
directory where the files actually are. My guess is that in the non-virt case, the current working directory defaults to the first (and only) preopen, i.e. /usr
, whereas in the virt case the current working directory is something else, e.g. /
. Is that plausible?
@Joel Dice the preopen would be /
in this case
but yes, that's correct
but I did find it odd too that all paths start with local but it's not apparent if the workdis is /usr
@Joel Dice but yeah, I switched from mounting usr/ to /usr and instead mounting root/ to / during writing the example, didn't change the behaviour so I left it at mounting /
Am I looking at out-of-date code, then? Looks like it's still /usr here: https://github.com/Gentle/repro-wasi-virt-python/blob/main/build.sh#L19
oh you're right, now I'm unsure if I did test that, sec
it might also be enlightening to print std::env::current_dir()
in the guest to see what the values are in the virt and non-virt cases.
(guess who has a 7 year old CPU... but I added the current_dir print before starting the build too)
ok so if you wasi-virt virtualize / it crashes earlier and actually in wasi-virt code
current_dir is always / though, no matter if I mount /usr or /
what is current_dir in the non-virt case?
(i.e. when everything works correctly)?
it's always /
in all 4 cases (with/without wasi-virt and with /
or with /usr
mounted)
this example is using a precompiled libpython in release mode, would linking against a debug build of python result in better backtraces? I still haven't fully grasped your build.rs
Not sure. It's worth a shot. Might also be worth reading through the CPython source code and adding log statements to it.
BTW, did you ever try setting PYTHONPATH
and PYTHONHOME
? I realize that won't help us understand difference in virt vs. non-virt behavior, but it might get you unstuck at least.
again, what is PYTHONPATH if no python binary exists?
still /usr/local/bin
?
componentize-py
sets PYTHONHOME to a mount of cpython/builddir/wasi/install/lib/python3.11 and sets PYTHONPATH to that same mount, plus any other directories that contain Python dependencies.
so if cpython/builddir/wasi/install/lib/python3.11 is mounted at /python, then PYTHONHOME=/python and PYTHONPATH=/python:/foo:/bar, where /foo and /bar might contain other .py files, etc.
replace cpython/builddir/wasi/install
in the above with whatever you set --prefix
to when you built CPython for WASI
@Guy Bedford I'm curious, why do some of these paths start with // and some with /?
Virtualized files from local filesystem:
- //usr/local/lib : wasi-root/usr/local/lib
- //usr/local/lib/python3.11 : wasi-root/usr/local/lib/python3.11
- //usr/local/lib/python3.11/lib-dynload : wasi-root/usr/local/lib/python3.11/lib-dynload
- //usr/local/lib/python3.11/lib-dynload/.empty : wasi-root/usr/local/lib/python3.11/lib-dynload/.empty
- //usr/local/lib/python3.11/os.py : wasi-root/usr/local/lib/python3.11/os.py
- //usr/local/lib/python311.zip : wasi-root/usr/local/lib/python311.zip
- /usr : wasi-root/usr
- /usr/local : wasi-root/usr/local
this is the output for --mount /=wasi-root/
I've pushed the version that mounts / and crashes even before python prints the error message
CALL wasi:filesystem/types#get_type FD=0
CALL wasi:io/streams#blocking_write_and_flush SID=2
[guest/src/lib.rs:12] std::env::current_dir() = CALL wasi:io/streams#blocking_write_and_flush SID=2
OkCALL wasi:io/streams#blocking_write_and_flush SID=2
(
CALL wasi:io/streams#blocking_write_and_flush SID=2
CALL wasi:io/streams#blocking_write_and_flush SID=2
"CALL wasi:io/streams#blocking_write_and_flush SID=2
/CALL wasi:io/streams#blocking_write_and_flush SID=2
"CALL wasi:io/streams#blocking_write_and_flush SID=2
,
CALL wasi:io/streams#blocking_write_and_flush SID=2
)CALL wasi:io/streams#blocking_write_and_flush SID=2
CALL wasi:filesystem/types#readlink_ FD=0 PATH=.
thread 'main' panicked at host/src/main.rs:92:54:
called `Result::unwrap()` on an `Err` value: error while executing at wasm backtrace:
0: 0x20dc735 - <unknown>!<wasm function 110>
1: 0x40d7 - <unknown>!<wasm function 68>
2: 0x20cbcfb - wit-component:shim!indirect-wasi:filesystem/types-readlink-at
3: 0x20c8570 - wit-component:adapter:wasi_snapshot_preview1!wasi_snapshot_preview1::bindings::wasi::filesystem::types::readlink_at::he5ee92fe9a3edb88
4: 0x20c48fb - wit-component:adapter:wasi_snapshot_preview1!path_readlink
5: 0x20cbfc9 - wit-component:shim!adapt-wasi_snapshot_preview1-path_readlink
6: 0xc52568 - <unknown>!__wasi_path_readlink
7: 0xc5296e - <unknown>!__wasilibc_nocwd_readlinkat
8: 0xc539ee - <unknown>!readlink
9: 0x2cca68 - <unknown>!_Py_wreadlink
10: 0x2ad007 - <unknown>!getpath_realpath
11: 0x47bc0 - <unknown>!cfunction_call
12: 0x2f4a6f - <unknown>!_PyObject_MakeTpCall
13: 0x2f43f9 - <unknown>!_PyObject_VectorcallTstate
14: 0x2f5a8c - <unknown>!PyObject_Vectorcall
15: 0x28dad4 - <unknown>!_PyEval_EvalFrameDefault
16: 0x26bd41 - <unknown>!_PyEval_EvalFrame
17: 0x26b701 - <unknown>!_PyEval_Vector
18: 0x26b402 - <unknown>!PyEval_EvalCode
19: 0x2a9fac - <unknown>!_PyConfig_InitPathConfig
20: 0x2be0c2 - <unknown>!config_init_import
21: 0x2be04a - <unknown>!_PyConfig_InitImportConfig
22: 0xbe69e6 - <unknown>!init_interp_main
23: 0xbe605d - <unknown>!pyinit_main
24: 0xbe5b95 - <unknown>!Py_InitializeFromConfig
25: 0xbe7513 - <unknown>!Py_InitializeEx
26: 0xc2dcbb - <unknown>!pyo3::gil::prepare_freethreaded_python::{{closure}}::h7c6b1ea7a1e67b74
27: 0xc2bf27 - <unknown>!parking_lot::once::Once::call_once_force::{{closure}}::h5c081b1fa0024754
28: 0xc3a82b - <unknown>!parking_lot::once::Once::call_once_slow::h6ee34d935790bed0
29: 0xc2bdbe - <unknown>!parking_lot::once::Once::call_once_force::h0586f871a09e24ad
30: 0xc2dc79 - <unknown>!pyo3::gil::prepare_freethreaded_python::hf2c84c00e83d0f7e
31: 0xb85f - <unknown>!<guest::Repro as guest::Guest>::version::h50616f722a26c1a7
32: 0xb8bf - <unknown>!version
I think I've found the or at least a culprit
there's diverging behaviour in readlink
without wasi-virt:
[guest/src/lib.rs:13] std::fs::read_link(".") = Err(
Os {
code: 28,
kind: InvalidInput,
message: "Invalid argument",
},
)
with wasi-virt:
[guest/src/lib.rs:13] std::fs::read_link(".") = Err(
Os {
code: 44,
kind: NotFound,
message: "No such file or directory",
},
)
and Python happens to excessively use readlin to check if any filename is a link https://github.com/python/cpython/blob/main/Python/fileutils.c#L2049-L2093
@Ramon Klass I've posted a fix for the double slashing in https://github.com/bytecodealliance/WASI-Virt/pull/27. For the issue you've traced down, have you tried mounting the .
preopen itself? There might be some subtleties here around current directory handling. The other thing to note is that the FS virtualization doesn't currently support symlinks at all.
Between current dir handling and symlinks support it sounds like that is where the issue lies. I'm happy to look into directions further, but also don't want to speculate on the solution either.
@Guy Bedford fully agreed, I think if anything this shows how far you've come, it doesn't crash, just answers wrongly to some api calls
for now I'm glad with how far it gets already, it's not a show stopper for me personally since I can deploy the wasi-root directory, and I don't think it's wise to brute force the specific issue right now instead of properly designing symlink support at the right time
about mounting something to .
, pythin still seems to call readlink_ as first call, but I'll try it when I have time
I've created https://github.com/bytecodealliance/WASI-Virt/issues/28 to track
@Ramon Klass here's a PR that removes the panic on a readlink call - https://github.com/bytecodealliance/WASI-Virt/pull/30
installing
I've added some further commits which fix some intermediate issues as well
progress :D
CALL wasi:filesystem/types#readlink_ FD=0 PATH=.
CALL wasi:filesystem/types#readlink_ FD=0 PATH=.
CALL wasi:filesystem/types#readlink_ FD=0 PATH=..
CALL wasi:filesystem/types#readlink_ FD=0 PATH=../..
CALL wasi:filesystem/types#readlink_ FD=0 PATH=../../..
CALL wasi:filesystem/types#readlink_ FD=0 PATH=../../../../..
CALL wasi:filesystem/types#readlink_ FD=0 PATH=../../../../../../../../..
CALL wasi:filesystem/types#readlink_ FD=0 PATH=../../../../../../../../../../../../../../../../..
CALL wasi:filesystem/types#readlink_ FD=0 PATH=../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../..
CALL wasi:filesystem/types#readlink_ FD=0 PATH=../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../..
CALL wasi:filesystem/types#readlink_ FD=0 PATH=../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../..
CALL wasi:filesystem/types#readlink_ FD=0 PATH=../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../..
CALL wasi:filesystem/types#readlink_ FD=0 PATH=../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../..
CALL wasi:filesystem/types#readlink_ FD=0 PATH=../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../..
CALL wasi:io/streams#blocking_write_and_flush SID=2
Exception ignored error evaluating pathCALL wasi:io/streams#blocking_write_and_flush SID=2
@Ramon Klass make sure to pull the latest - I already fixed that one :)
damn you wasm-opt-sys, I'm still waiting on the new build and having a C++ dependency doesn't help ;)
@Ramon Klass I just got it working against https://github.com/bytecodealliance/WASI-Virt/pull/30 I think actually
with the latest changes again
please try that out and let me know if that seems like it's working
kinda exciting if it is!
side question while it rebuilds, why do you have binaries commited in lib/?
actually now that I think about it, cargo install can't run preinstall scripts unless there's some way I don't know, and youi can't run cargo in build.rs so I think I answered my question myself
good point, added https://github.com/bytecodealliance/WASI-Virt/pull/30
oh wait yeah that's the reason
well, you CAN set CARGO_TARGET_DIR in build.rs and then run cargo but that then creates two independant compiler caches
once it's published to cargo we can remove that
Initializing non-virtualized component with preopened dir
Response: 3.11.4 (tags/v3.11.4:d2340ef, Jul 14 2023, 11:21:37) [Clang 16.0.0 ]
Initializing virtualized component without preopened dir
Response: 3.11.4 (tags/v3.11.4:d2340ef, Jul 14 2023, 11:21:37) [Clang 16.0.0 ]
this is amazing
are you merging pull/30 or should I depend on the symlinks branch now? :D
so uh, since we now have a python component that doesn't need a filesystem anymore, we have to run that on jco next, right? ;)
it's a 37 MB static website but it does just work
amazing, the pieces do work :)
Congratulations to everyone discovering that CPython is one of the best POSIX (and C standard compiler) test suites out there. :grinning_face_with_smiling_eyes:
It sounds like nothing needs to change in how CPython is built, correct?
@Guy Bedford I have updated the repro, importing a pure python module from site-packages fails to read the files, I've added the two versions to the host again to see what it should do https://github.com/Gentle/repro-wasi-virt-python/
wait the debug output looks like it did interpret some of the code, it reads the files in order of imports
also sorry for highlighting
Last updated: Nov 22 2024 at 16:03 UTC