Hi all

Please CC me any replies since I don't currently subscribe to this list.

I am trying to create a statically linked X application to simplify
distribution.  Up to and including Xfree86 4.1.0 everything worked fine by
passing "-static" to gcc during the link stage.

Starting with Xfree86 4.2.0, the application linked this way started to give
strange and unpredictable segfaults during operation.  It was a wxgtk app,
and I started stripping out code to eliminate as many things as possible. 
Eventually I had a plain gtk application skeleton which triggered the fault.

I found that if the system's libX11.a was replaced with the one from Xfree86
4.1.0 that the problem went away.

Subsequently I found that if the dynamic locale loader was disabled in
libX11 the program was stable.  Similarly, if <X11
root>/lib/X11/locale/common/xlcDef.so.2 was removed the problem went away.

The segfault was always in __libc_free(), called from XmbSetWMProperties().
This later function is called for each new window created by gtk
(gdk_window_new()) and it was at this point (ie: window creation) that the
segfault was occuring.

In this instance mbWMProps.c:XmbSetWMProperties() is used to set the name
and icon name for the window being created.  This passes the name and icon
name through lcWrap.c:XmbTextListToTextProperty(), presumedly to allow for
locale modifications.  XmbTextListToTextProperty() essentially handballs the
request to the locale's mb_text_list_to_prop method.

The problem with statically linked executables is that xlcDef.so.2 is
actually a dynamic library with dependencies on libX11.so and libc.so.  Thus
when xlcDef.so.2 is loaded with dlopen(), the dynamic libX11 and libc
libraries are dragged into core to satisfy these dependencies.  For dynamic
applications the second copies aren't dragged in - dlopen() uses the incore
copies to resolve references; for statically linked applications, however,
the static core copy can't be used.  For static executables, from this
point, we have two libc/X11 environments - one used by xlcDef.so.2 and one
used by every other component of the program.

Note that source filenames which follow are from xc/lib/libX11/.

On our systems, the default `C' locale is handled by the dynamic 
/usr/X11R6/lib/X11/locale/common/xlcDef.so.2 module.  In this module, the
locale's mb_text_list_to_prop method remains pointed to the default class
method, which is lcTxtPr.c:_XTextListToTextProperty().  This setting is made
in the lcPublic.c:initialize_core() function, called from
lcPubWrap.c:_XlcCreateLC() which is in turn called by the module's loader
(lcDefConv.c:_XlcDefaultLoader()), which itself is called when the module is
initially loaded in XlcDL.c:_XlcDynamicLoad().  Significantly, everything
from _XlcDefaultLoader() down is running with the dynamic shared copies of
libX11 and libc - so the mb_text_list_to_prop method pointer is set to point
to the shared library's _XTextListToTextProperty() function.

When memory allocation is done by either libc, the other has no way of
knowing what is being done.  Therefore it is only a matter of time before
one of the libc/X11's corrupts the heap of the other.

In my case, the locale module does do memory allocation with
malloc()/free().  _XTextListToTextProperty() makes a buffer allocation
before calling the appropriate conversion functions from the locale module,
which in our case are (in order)
  lcDefConv.c:open_mbstostr()
  lcDefConv.c:create_conv()
  lcDefConv.c:mbstostr()
  lcDefConv.c:close_converter()
If XmbTextListToTextProperty() is allowed to pass its request to the
locale's mb_text_list_to_prop method, this results in a call to a copy of 
_XTextListToTextProperty() which lies within the shared library loaded along
with the locale module - not the copy in the (static) program's core.  Thus
the application's heap memory is being used concurrently by two different
libcs and eventually one will corrupt the other.  Once this corruption
occurs, the segfault happens.

Therefore, we finally come to my question: 

 * given this new dynamic locale functionality, how exactly is one to make 
   a static executable which will run on all systems?

Essentially, as I see it, static X libs compiled under Xfree86 4.2.0 will
work on all systems which don't have the dynamic locale modules installed
(eg: XFree86 systems <4.1.0), but will segfault and/or be unstable on
systems which have the dynamic locale modules available.

Regards
  jonathan
-- 
* Jonathan Woithe    [EMAIL PROTECTED]                        *
*                    http://www.physics.adelaide.edu.au/~jwoithe            *
***-----------------------------------------------------------------------***
** "Time is an illusion; lunchtime doubly so"                              **
*  "...you wouldn't recognize a subtle plan if it painted itself purple and *
*   danced naked on a harpsichord singing 'subtle plans are here again'"    *
_______________________________________________
Xpert mailing list
[EMAIL PROTECTED]
http://XFree86.Org/mailman/listinfo/xpert

Reply via email to