More Ubuntu madness…
Thursday, September 29th, 2005Recently I updated my Ubuntu installation. After the update many of my java applications stopped working. Any java application that attempted to display something via X11 terminates with the following error:
current locale is not supported in X11, locale is set to CX locale modifiers are not supported, using default
You can google for possible solutions, which I did. This problem is also discussed in detail in the Ubuntu Forums.
They claim that this bug is known and has been fixed.
Well it isn’t. I tried all the other suggestions for the fix, but none of them work for me.
I have two solutions:
- Run it in a 32-bit chroot environment (see this link. But this gets pretty annoying if you have a lot of different executables. Then I might as well ditch this 64-bit OS and install the 32-bit one.
- Hack the 32-bit libX11.so.6.2 library. Keep reading if you are interested in this hack.
The Hack
- Create a backup of /usr/X11R6/lib32/libX11.so.6.2
- Edit /usr/X11R6/lib32/libX11.so.6.2 in the emacs editor (any other binary editor should work)
- search for the string
/usr/X11R6/lib/X11/locale - replace it with
/usr/X11R6/l32/X11/locale
- search for the string
- Save the file and exit emacs
- Go to the /usr/X11R6 directory
- Create a symlink called l32 that points to lib32 in that same directory
- Go to the /usr/X11R6/lib32/X11/locale directory
- Create symlinks here to all the files (except lib) that exists in
/usr/X11R6/lib/X11/locale - You’re done
After applying this hack, my 32-bit java programs now run without complaining about locales.
Why this hack works
Since none of the workarounds and fixes I’ve found in Google and the Ubuntu Forums worked for me, I decided to do some strace’ing myself.
Strace showed that the program was opening /usr/X11R6/lib/X11/locale/lib/common/xlcUTF8Load.so.2. Now I know that the Java I installed is a 32-bit executable, and this library is a 64-bit binary. So my guess is that the linker fails to link with this library. To test my hypothesis, I replaced this library (after creating a backup of course) with the one from /usr/X11R6/lib32/X11/locale/lib/common/xlcUTF8Load.so.2 (the 32-bit counterpart). Just this simple operation, fixed my problem. However it introduces another one: all other 64-bit X applications complained about my locale (although they continued to work). I had to come up with a way to have both types of applications working.
I restored the original xlcUTF8Load.so.2 to keep my 64-bit X applications happy. Now I needed a way to get my 32-bit applications to link with the 32-bit xlcUTF8Load.so.2 library.
From the strace output, I compiled a list of all the X libraries that the application opened. Then I searched those libraries for the string “/usr/X11R6/lib/X11/locale”. The culprit was libX11.so.6.2.
I needed to modify this library to look at /usr/X11R6/lib32/X11/locale in order for it to find the correct version of xlcUTF8Load.so.2. Simply replacing ‘lib’ with ‘lib32′ will not work since it will change the size of the library, and mess up whatever offsets are setup in that library. I needed to replace ‘lib’ with an equal length string that points to the correct place. So I replaced it with ‘l32′, then created a symlink called l32 which points to lib32 in /usr/X11R6.
After doing this, I tested my application, and it continued to fail. What was going wrong? Further strace output showed that the app was no longer linking xlcUTF8Load.so.2. The strace output also showed a bunch of open() failures for files that lived in /usr/X11R6/l32/X11/locale. Those files exist in /usr/X11R6/lib/X11/locale. So by creating symlinks to all those files, the behavior of the application was restored (it once again discovered that it needed xlcUTF8Load.so.2).
Now all my java programs work again without sacrificing the functionality of my 64-bit X applications. And possibly other 32-bit X11 applications will also work with proper locale support.
Update: I have made additional hacks to get acroread to work.
1. create a symlink called /usr/l32 pointing to /usr/lib32
2. modify the libraries found in /lib32, /usr/lib32, and /usr/X11R6/lib32 to use /usr/l32 instead of /usr/lib
* /usr/lib32/libglib-2.0.so.0.400.7
* /usr/lib32/libgdk_imlib.so.1.9.14
* /usr/lib32/libgtk-1.2.so.0.9.1
* /usr/lib32/libgtk-x11-2.0.so.0.400.10
* /usr/lib32/libgdk_pixbuf-2.0.so.0.400.10
** change to this is tricky. Look for gtk-2.0 followed by “/etc” then change gtk-2.0 to g32-2.0
** copy /etc/gtk-2.0 to /etc/g32-2.0 and modify the gdk-pixbuf.loaders and gtk.immodules files inside the /etc/g32-2.0 to point to /usr/lib32 versions of the files
3. modify /lib32/tls/libc-2.3.2.so
** change /usr/lib/gconv to /usr/l32/gconv
** change /usr/lib/gconv/gconv-modules.cache to /usr/l32/gconv/gconv-modules.cache
4. modify /usr/lib32/libpango-1.0.s0.0.1000.0
** change /usr/lib to /usr/l32
** change /etc/pango to /etc/pgo32
** copy /etc/pango to /etc/pgo32
** modify /etc/pgo32/pango.modules to change /usr/lib into /usr/lib32
Update 2: I have upgraded to dapper (6.06 LTS). My hacks broke in this version because the libpango-1 library uses /var/lib/pango/pango.modules. The fix is to modify /usr/lib32/libpango-1.0.so.0.1201.2 and replace all occurances of /var/lib/pango with /var/lib/pgo32, then create a directory called /var/lib/pgo32 and copy the contents of /var/lib/pango into /var/lib/pgo32. Then edit /var/lib/pgo32/pango.modules and replace all occurances of “/usr/lib” with “/usr/lib32″.
-- Posted in Geeks Paradise