From: Tristan Savatier Subject: Using threads and Xlib: a simple patch to linuxthreads! Newsgroups: comp.os.linux.development.apps Date: Fri, 23 Jan 1998 14:48:54 -0800 Organization: MpegTV, http://www.mpegtv.com Path: pubxfer.news.psi.net!pubxfer.news.psi.net!psinntp!news.columbia.edu!sol.ct r.columbia.edu!news.indiana.edu!news1.chicago.iagnet.net!iagnet.net!news.idt.net !news-peer-east.sprintlink.net!news.sprintlink.net!Sprint!nntp.abs.net!out2.nntp .cais.net!news2.cais.com!not-for-mail Lines: 133 Message-ID: <34C91E56.31DD0792@mpegtv.com> NNTP-Posting-Host: port27.creative.net Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit X-Mailer: Mozilla 3.01 (X11; I; Linux 2.0.27 i586) Xref: pubxfer.news.psi.net comp.os.linux.development.apps:49177 X-Cache: nntpcache 1.0.7.1 (see ftp://suburbia.net/pub/nntpcache) I believe that this message is interesting for people using posix threads on systems like Linux, specially in applications using non-thread-safe libraries or libraries not compiled with -D_REENTRANT in most distributions, like Xlib. One of the most ennoying problem with using threads on systems like Linux is that most libraries (including Xlib) are generally not compiled to work with threads, which makes it difficult to use threads in applications that interact with them. I typical problem when using threads in an application using Xlib is the famous: XIO: fatal IO error 0 (Unknown error) on X server ":0.0" See details on http://pauillac.inria.fr/~xleroy/linuxthreads/faq.html#H It should be no problem as long as all the non-thread-safe libraries are called from the main thread, provided that the address of "errno" of the main thread is the same as address of the "int errno" defined in libc. When a program is compiled to use threads, the macro _REENTRANT is defined, causing errno to become a macro defined as (* __errno_location()), i.e. the address of errno is returned by a routine, and is different for each thread. In case some routines (maybe part of a library) were compiled with -D_REENTRANT (but are not explicitely using threads), libc takes care of defining a dummy __errno_location() routine that returns the address of "int errno". Until then, all is fine... But the problem start when linking with -lpthread: libpthread redefines __errno_location() to return an address different for each thread, unfortunately always different from the address of "int errno", even in the main thread! This causes havoc if the main thread is using a mix of things compiled with and without -D_REENTRANT, which is often the case (because of libraries). Because of that, the meer fact of adding -lpthead when linking an application that uses Xlib (but does not use threads!) causes the application to die with the famous: XIO: fatal IO error 0 (Unknown error) on X server ":0.0" I found an easy way to solve this problem with the very small change in the way __errno_location() is defined in the thread library. I implemented this minuscule change in linuxthread-0.71, and was able to run a large and complex Xlib application while using threads (as long as all the Xlib calls were made from the main threads), and I did not have to recompile any other library!!! Here is the patch: ==================== old version of errno.c (from linuxthreads-0.71): #define _REENTRANT #include #include "pthread.h" #include "internals.h" int * __errno_location() { pthread_descr self = thread_self(); return &(self->p_errno); } int * __h_errno_location() { pthread_descr self = thread_self(); return &(self->p_h_errno); } ==================== my patched version: #include #define _REENTRANT #include "pthread.h" #include "internals.h" int * __errno_location() { pthread_descr self = thread_self(); if (self == __pthread_main_thread) return &errno; return &(self->p_errno); } int * __h_errno_location() { pthread_descr self = thread_self(); return &(self->p_h_errno); } ======================= explanation: The patch guarantees that errno, even when defined as the macro (* __errno_location()), will correspond to the "int errno" declared in libc, as long as we are in the main thread. NOTE the important change in the order of the first 2 lines! errno.h must be included BEFORE defining _REENTRANT, to make sure that errno is defined as "extern int errno", not as (* __errno_location()). This patch allows using Xlib in a multithreaded program, (or using threads in a program that uses Xlib) with one restriction: all the Xlib calls have to be made from the main thread. I tested it sucessfully with a very complex X11 application (namely the MpegTV Player, a real-time MPEG player). I was to start a few other threads, without any problem, while the main thread is using the Xlib library. I believe this patch should be included in the linuxthread distribution and in other thread packages. In any case, it took 5 minutes to patch the linuxthreads distribution, so anyone interested can try it. -- Regards, -- Tristan Savatier (President, MpegTV LLC) MpegTV: http://www.mpegtv.com