Error: main: Could not initialize canvas
This error message is not too helpful, but an important thing to check is if the Wayland socket can be found. If not, glmark2-wayland cannot create a surface/canvas.
The convention is that the Wayland socket directory is specified by the $XDG_RUNTIME_DIR
environment variable. The default name for the socket is wayland-0
but it can be different (specified by $WAYLAND_DISPLAY
).
Generally, $XDG_RUNTIME_DIR
is set to /run/user/$UID
where $UID
is the user id.
- Ubuntu Desktop:
ubuntu-frame
creates the Wayland socket at /run/user/$UID/wayland-0
, where $UID
is your user id.
- Ubuntu Core:
ubuntu-frame
runs as root on Core, thus the Wayland socket is located at /run/user/0/wayland-0
However inside each snap’s environment, $XDG_RUNTIME_DIR
is a custom subdirectory. To see this, this command gives a shell inside the same snap environment your application lives:
sudo snap run --shell glmark2-example
user@in-snap:~# echo $XDG_RUNTIME_DIR
/run/user/1000/snap.glmark2-example
This reveals a problem with the Wayland socket not being in the right location for the application snap.
The solution we use is to symlink the Wayland socket into the in-snap $XDG_RUNTIME_DIR
(and to be safe, ensure the directory exists before adding the link):
user@in-snap:~# mkdir -p $XDG_RUNTIME_DIR
user@in-snap:~# ln -s $XDG_RUNTIME_DIR/../wayland-0 $XDG_RUNTIME_DIR/
We could override the value of $XDG_RUNTIME_DIR
in the app snap to be /run/user/0. The reason we do not is for avoiding later problems with strict confinement. In strict mode on Ubuntu Core, AppArmor will deny access to anything in that directory aside from the Wayland socket:
root@in-snap-strict:~# ls /run/user/0
ls: cannot open directory '/run/user/0': Permission denied
root@in-snap-strict:~# ls /run/user/0/wayland-0
/run/user/0/wayland-0
“sudo journalctl -r
” will show the AppArmor denial:
AVC apparmor="DENIED" operation="open" profile="snap.glmark2-example.glmark2-example" name="/run/user/0/" pid=24664 comm="ls" requested_mask="r" denied_mask="r" fsuid=0 ouid=0)
Let’s test it:
user@in-snap:~# $SNAP/usr/bin/glmark2-wayland
/snap/glmark2-example/x1/usr/bin/glmark2-wayland: error while loading shared libraries: libjpeg.so.8: cannot open shared object file: No such file or directory
Yikes! What’s happened?
Once again: files are not where they’re expected to be! Don’t forget, we’re in the snap environment still. All the libraries glmark2-wayland needs are not in the usual places - we need to tell it where.
Run these commands to set the linker paths $LD_LIBRARY_PATH
and executable paths $PATH
to commonly required locations in the snap environment (snapd does this before running your snap):
root@in-snap:~# export PATH="$SNAP/usr/sbin:$SNAP/usr/bin:$SNAP/sbin:$SNAP/bin:$PATH"
root@in-snap:~# export LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${SNAP}/usr/lib/:${SNAP}/usr/lib/x86_64-linux-gnu/"
Note: you should add any additional library paths that the binary requires.
Snapcraft creates a script in $SNAP
that contains the command specified to run. Have a look at
root@in-snap:~# cat $SNAP/command-glmark2-example.wrapper
#!/bin/sh
exec "$SNAP/usr/bin/glmark2-wayland" "--fullscreen" "$@"
It is this script which is called when you do “snap run …”. As we are still in the snap environment, we get the same result by running it:
root@in-snap:~# $SNAP/command-glmark2-example.wrapper
Oh, still fails with a bunch of errors like
Error: eglGetDisplay() failed with error: 0x3000
Error: eglGetDisplay() failed with error: 0x3000
Error: main: Could not initialize canvas
Courage! This is progress, we’re almost done in fact. There’s just one more thing to fix…