<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Oct 16, 2014 at 11:16 PM, Pekka Paalanen <span dir="ltr"><<a href="mailto:ppaalanen@gmail.com" target="_blank">ppaalanen@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">On Thu, 16 Oct 2014 10:40:20 +0300<br>
Pekka Paalanen <<a href="mailto:ppaalanen@gmail.com">ppaalanen@gmail.com</a>> wrote:<br>
<br>
> On Thu, 16 Oct 2014 09:46:39 +0300<br>
> Pekka Paalanen <<a href="mailto:ppaalanen@gmail.com">ppaalanen@gmail.com</a>> wrote:<br>
><br>
> > On Wed, 15 Oct 2014 22:44:25 +0400<br>
> > Dmitry Cherkassov <<a href="mailto:dcherkassov@gmail.com">dcherkassov@gmail.com</a>> wrote:<br>
> ><br>
> > > Hi list!<br>
> > ><br>
> > > The definition of wl_display_interface symbol can come from<br>
> > > libwayland-server.so or libwayland-client.so.<br>
> > ><br>
> > > There is a code in closed source EGL implementation that does<br>
> > > interfaces comparison via pointers, yielding negative results when<br>
> > > addresses are different (one address is saved by QtWayland, the other<br>
> > > one is from &wl_display_interface in EGL source code).<br>
> > ><br>
> > > Is there a smarter way to compare wl_display_interface's?<br>
> > ><br>
> > > There is this function:<br>
> > ><br>
> > > wl_interface_equal(const struct wl_interface *a, const struct wl_interface *b)<br>
> > > {<br>
> > > return a == b || strcmp(a->name, b->name) == 0;<br>
> > > }<br>
> > ><br>
> > > But as you can see it's not safe to use it alone because in case of<br>
> > > bad pointer we will get undefined results.<br>
> > ><br>
> > > Currently struct wl_interface is the following:<br>
> > > struct wl_interface {<br>
> > > const char *name;<br>
> > > int version;<br>
> > > int method_count;<br>
> > > const struct wl_message *methods;<br>
> > > int event_count;<br>
> > > const struct wl_message *events;<br>
> > > };<br>
> > ><br>
> > > Since there is no magic field at the beginning it is not possible to<br>
> > > see whether a pointer points to the valid wl_interface structure.<br>
> > ><br>
> > > So my question is: how can we compare wl_interfaces in more clever and<br>
> > > safer way?<br>
> ><br>
> > Hmm, why would you ever have a bad pointer?<br>
> ><br>
> > Bad pointers in general tend to cause crashes and stuff, so you<br>
> > shouldn't be having a bad one in the first place.<br>
> ><br>
> > What is the background for your question/problem?<br>
><br>
> Ok, I suppose this was discussed in IRC last night: the actual problem<br>
> behind the question is how to detect whether the void pointer<br>
> (EGLNativeDisplayType) given to eglCreateDisplay is actually a<br>
> wl_display.<br>
><br>
> That's tough.<br>
><br>
> A couple of hacks come to mind.<br>
><br>
> bool<br>
> _eglNativePlatformDetectWayland(void *nativeDisplay)<br>
> {<br>
> void *f;<br>
><br>
> if (!dereferencable(nativeDisplay))<br>
> return false;<br>
><br>
> f = *(void **)nativeDisplay;<br>
><br>
> The first is to dlopen both libwayland-client and libwayland-server in<br>
> turn with RTLD_NOLOAD | RTLD_LOCAL, and fetching the<br>
> wl_display_interface symbol from each, comparing those to 'f'. If<br>
> either matches, return true.<br>
<br>
While discussing in IRC, I realized half of this is nonsense.<br>
<br>
eglGetDisplay() can only get a wl_display created by libwayland-client,<br>
and never one created by libwayland-server. Assuming the dynamic<br>
linking is sane, the interface pointer in wl_display is *always* the<br>
one from libwayland-client.so.<br>
<br>
Now we just need to make sure, that we compare 'f' to the interface<br>
pointer from libwayland-client.so. That could probably be done with the<br>
dlopen/dlsym trick, or...<br>
<br>
> Another would be to check if 'f' is dereferencable (and not equal to<br>
> the default wl_display_interface), and check if (char *)f starts with<br>
> "wl_d". If yes, do a full string comparison with "wl_display". It's<br>
> not reliable, but maybe works enough.<br>
><br>
> The proper solution is for apps to use EGL_KHR_platform_wayland to<br>
> explicitly say the pointer is a wl_display. That of course doesn't work<br>
> on old apps, so you might implement a workaround through environment<br>
> like Mesa does: EGL_PLATFORM=wayland bypasses all autodetection and<br>
> assumes it is a wl_display.<br>
><br>
> In any case, EGL really should implement EGL_KHR_platform_wayland so we<br>
> have a chance to get rid of the inherently unreliable autodetect. And we<br>
> should start using that in our demo apps...<br>
><br>
> If we consider autodetecting client wl_display pointers worth to solve<br>
> properly, we should probably add a function for that in<br>
> libwayland-client.so. However, implementing that portably might be<br>
> difficult.<br>
<br>
...adding a function int/bool wl_is_wl_display_pointer(void *p) into<br>
libwayland-client.so. As that function would be built into<br>
libwayland-client.so, it naturally uses the client.so version of<br>
wl_display_interface symbol (unless dynamic linking miraculously<br>
manages to mess that up?).<br>
<br>
'p' would be the tentative 'struct wl_display *', so that the<br>
implementation details of struct wl_display would be contained in<br>
libwayland-client.so, and not leaked elsewhere like e.g. in Mesa.<br>
<br>
All this means we should be able to get away with just one pointer<br>
comparison, after assuring that the first sizeof(void*) bytes pointed<br>
to by the given unknown pointer (EGLNativeDisplayType) are<br>
dereferencable without a segfault or other fatal error.<br>
<br>
So, a quick fix for EGL implementations right now would be to try the<br>
dlopen hack, until they can start to depend on a new<br>
libwayland-client.so providing wl_is_wl_display_pointer().<br>
<br>
I am unsure about the exact definition of wl_is_wl_display_pointer():<br>
can it do the dereferencability check itself, or should we require the<br>
caller to guarantee that dereferencing cannot crash. The latter would<br>
leave the portability burden on the callers rather than libwayland.<br>
<br>
How's that sound?<br></blockquote><div> <br></div><div>That sounds fine. I think we can count on the client passing in a valid pointer to something. Chances are that whatever the client passes in will be a pointer to some sort of structure and so we can probably read 8 bytes without a problem. If we really wanted to, we could do a quick alignment check to ensure that it's sizeof(void *)-aligned.<br><br></div><div>I don't know that I care whether we do your wl_is_wl_display_pointer or Bill's "dynamic cast" version. It doesn't much matter.<br></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
Is it possible to have several instances of libwayland-client in a<br>
process address space? Meaning we would have several different<br>
client-side wl_display_interface pointers?<br></blockquote><div><br></div><div>I don't think so. At least not without some very bizarre hackery. Also, I think it's reasonable to assume that either a) libEGL is reasonably normally linked against the same chunks of code that link to libwayland-client or b) The client really knows what they're doing and is prepared for the consequences. Because really, if they're pulling those kinds of tricks they're asking for trouble.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
If yes, it's back to the string comparisons...<br></blockquote><div><br></div><div>String comparisons are right out. They'll cause a segfault the moment it's not a wl_display pointer. <br></div></div>--Jason<br></div></div>