Smart comparing of wl_display_interfaces

Pekka Paalanen ppaalanen at gmail.com
Thu Oct 16 00:40:20 PDT 2014


On Thu, 16 Oct 2014 09:46:39 +0300
Pekka Paalanen <ppaalanen at gmail.com> wrote:

> On Wed, 15 Oct 2014 22:44:25 +0400
> Dmitry Cherkassov <dcherkassov at gmail.com> wrote:
> 
> > Hi list!
> > 
> > The definition of wl_display_interface symbol can come from
> > libwayland-server.so or libwayland-client.so.
> > 
> > There is a code in closed source EGL implementation that does
> > interfaces comparison via pointers, yielding negative results when
> > addresses are different (one address is saved by QtWayland, the other
> > one is from &wl_display_interface in EGL source code).
> > 
> > Is there a smarter way to compare wl_display_interface's?
> > 
> > There is this function:
> > 
> > wl_interface_equal(const struct wl_interface *a, const struct wl_interface *b)
> > {
> >     return a == b || strcmp(a->name, b->name) == 0;
> > }
> > 
> > But as you can see it's not safe to use it alone because in case of
> > bad pointer we will get undefined results.
> > 
> > Currently struct wl_interface is the following:
> >  struct wl_interface {
> >      const char *name;
> >      int version;
> >      int method_count;
> >      const struct wl_message *methods;
> >      int event_count;
> >      const struct wl_message *events;
> >  };
> > 
> > Since there is no magic field at the beginning it is not possible to
> > see whether a pointer points to the valid wl_interface structure.
> > 
> > So my question is: how can we compare wl_interfaces in more clever and
> > safer way?
> 
> Hmm, why would you ever have a bad pointer?
> 
> Bad pointers in general tend to cause crashes and stuff, so you
> shouldn't be having a bad one in the first place.
> 
> What is the background for your question/problem?

Ok, I suppose this was discussed in IRC last night: the actual problem
behind the question is how to detect whether the void pointer
(EGLNativeDisplayType) given to eglCreateDisplay is actually a
wl_display.

That's tough.

A couple of hacks come to mind.

bool
_eglNativePlatformDetectWayland(void *nativeDisplay)
{
	void *f;

	if (!dereferencable(nativeDisplay))
		return false;

	f = *(void **)nativeDisplay;

The first is to dlopen both libwayland-client and libwayland-server in
turn with RTLD_NOLOAD | RTLD_LOCAL, and fetching the
wl_display_interface symbol from each, comparing those to 'f'. If
either matches, return true.

Another would be to check if 'f' is dereferencable (and not equal to
the default wl_display_interface), and check if (char *)f starts with
"wl_d". If yes, do a full string comparison with "wl_display". It's
not reliable, but maybe works enough.

The proper solution is for apps to use EGL_KHR_platform_wayland to
explicitly say the pointer is a wl_display. That of course doesn't work
on old apps, so you might implement a workaround through environment
like Mesa does: EGL_PLATFORM=wayland bypasses all autodetection and
assumes it is a wl_display.

In any case, EGL really should implement EGL_KHR_platform_wayland so we
have a chance to get rid of the inherently unreliable autodetect. And we
should start using that in our demo apps...

If we consider autodetecting client wl_display pointers worth to solve
properly, we should probably add a function for that in
libwayland-client.so. However, implementing that portably might be
difficult.


Thanks,
pq


More information about the wayland-devel mailing list