Reported by SGI to old X.Org bug DB - the following is copied from X.Org Defect 8617 - unfortunately, in my copy, the end of the suggested fix got corrupted. VERSION: R6.3, public-patch-2 CLIENT MACHINE and OPERATING SYSTEM: SGI Indigo2 / SGI Challenge L / Irix 6.5 DISPLAY TYPE: SGI Indigo 2 XL WINDOW MANAGER: fvwm / 4Dwm COMPILER: native cc (7.2+) AREA: Xau SYNOPSIS: libXau is not thread safe. DESCRIPTION: Two variables (size,buf) in the function XauFileName are of storage class 'static' these need to be protected against multiple threads accessing them at the same time. REPEAT BY: The following sample code creates 10 (NUM_THREADS) threads, each with its own display connection/application context/mainloop [Note that the default server source only allows for 5 connections to be 'listened' on at once, so you may need to lower this/rebuild server]. The shell script (run.sh) loops continuously until the test program core dumps. Multiple processors make this more likely 8<------------------ run.sh ----------------------- #! /bin/sh rm -f core while [ ! -f core ] do echo $1 ./$1 -synchronous $2 done ls -l core 8<----------------------- threads.c ---------------------- #include <Xm/XmAll.h> #include <X11/Xthreads.h> #include <unistd.h> #include <stdlib.h> #include <errno.h> /* #define GADGETS */ #define TIMEOUT 10000 #define NUM_THREADS 10 typedef struct _ThreadData { int argc; char **argv; pthread_t id; int thread_num; XtAppContext app; Display *dsp; Widget shell; XEvent *event; } ThreadData; static char *fallbacks[] = { "*XmTextField.value: text field", "*XmText.value: text widget", "Shell.sgiMode: True", 0 }; void errorHandler(Display *dsp) { abort(); } void xtErrorHandler(char *msg) { abort(); } void xtErrorMsgHandler(String name, String type, String class, String def, String *params, Cardinal *num) { abort(); } static void nullTO(XtPointer client, XtIntervalId *id) { } static void timerCB(XtPointer client, XtIntervalId *id) { ThreadData *thread = (ThreadData *) client; XtAppSetExitFlag(thread->app); /* really bogus... We need to generate a fake event, to ensure that * XtAppNextEvent() unblocks. This wouldn't normally be a problem, since * XtAppSetExitFlag would be called from a Callback (probably from a pulldown * menu), the poping down of which would generate the event to unblock * XtAppNextEvent rmo */ XSendEvent(XtDisplay(thread->shell), XtWindow(thread->shell), False, 0, thread->event); } static void mapCB(Widget w, XtPointer client, XEvent *xev, Boolean *cont) { ThreadData *thread = (ThreadData *) client; if (xev->type == MapNotify) { thread->event = xev; XtAppAddTimeOut(thread->app, TIMEOUT, timerCB, client); } } static void * createShell(void *ptr) { ThreadData *thread = (ThreadData *) ptr; Widget top, rc, w; unsigned int num; char buf[20]; Arg args[10]; Display *dsp; num = thread->thread_num; #ifdef APP_INIT thread->shell = XtVaAppInitialize(&thread->app, "Shell", 0, 0, &thread->argc, thread->argv, fallbacks, XtNwidth, 100, XtNheight, 100, NULL); thread->dsp = XtDisplay(thread->shell); #else thread->dsp = XtOpenDisplay(thread->app,NULL, NULL, "Shell", NULL, 0, &thread->argc, thread->argv); thread->shell = XtVaAppCreateShell(NULL,"Shell", applicationShellWidgetClass, thread->dsp, XtNwidth, 100, XtNheight, 100, NULL); #endif /* APP_INIT */ XtAddEventHandler(thread->shell,StructureNotifyMask, False, mapCB, thread); /* XtAppAddTimeOut(thread->app, TIMEOUT, timerCB, thread); */ XtRealizeWidget(thread->shell); XtAppMainLoop(thread->app); XtDestroyApplicationContext(thread->app); return NULL; } main(int argc, char **argv) { unsigned int numThreads = NUM_THREADS; Boolean status; int i; /* don't need Xlib threads */ status = XInitThreads(); if (status) { puts("Xlib threads supported"); } else { puts("Xlib threads not supported"); exit(1); } status = XtToolkitThreadInitialize(); if (status) { puts("Xt threads supported"); } else { puts("Xt threads not supported"); exit(1); } XtToolkitInitialize(); XSetIOErrorHandler( (XIOErrorHandler) errorHandler); XtSetErrorMsgHandler( (XtErrorMsgHandler) xtErrorMsgHandler ); while(numThreads--) { ThreadData *thread = (ThreadData *) calloc(1, sizeof(ThreadData) ); thread->argc = argc; thread->argv = (char **) calloc(argc, sizeof(char *) ); thread->thread_num = numThreads; #ifndef APP_INIT thread->app = XtCreateApplicationContext(); #endif for (i=0; i< argc; i++ ) thread->argv[i] = XtNewString(argv[i]); pthread_create(&thread->id, NULL, createShell, (void *)thread); } pthread_exit(NULL); } SAMPLE FIX: /* $XConsortium: AuFileName.c /main/8 1996/09/28 16:43:20 rws $ */ [ piranha Jan04f ] p_rdiff -c AuFileName.c *** /usr/tmp/p_rdiff_16049/AuFileName.c Wed Feb 4 14:31:21 1998 --- AuFileName.c Wed Feb 4 14:31:12 1998 *************** *** 30,40 **** #include <X11/Xauth.h> #include <X11/Xos.h> char * XauFileName () { char *slashDotXauthority = "/.Xauthority"; ! char *name, *malloc (), *getenv (); #ifdef __sgi /* * PAGE USAGE TUNING: explicitly initialize to move these to data --- 30,53 ---- #include <X11/Xauth.h> #include <X11/Xos.h> + #ifdef _SGIBUGFIX + /* Bugworks #568635: offer jan 98 */ + #ifdef XTHREADS + #include <X11/Xlibint.h> + #endif /* XTHREADS */ + #endif /* _SGIBUGFIX */ + char * XauFileName () { char *slashDotXauthority = "/.Xauthority"; ! char *name, *getenv (); ! #ifdef _SGIBUGFIX ! #ifndef XTHREADS ! char *malloc(); ! #endif /* XTHREADS */ ! #endif /* _SGIBUGFIX */ ! #ifdef __sgi /* * PAGE USAGE TUNING: explicitly initialize to move these to data *************** *** 66,71 **** --- 79,89 ---- return 0; } size = strlen (name) + strlen(&slashDotXauthority[1]) + 2; + #ifdef _SGIBUGFIX + #ifdef XTHREADS + _XLockMutex(_Xglobal_lock); + #endif /* XTHREADS */ + #endif /* _SGIBUGFIX */ if (size > bsize) { if (buf) free (buf); *************** *** 76,80 **** --- 94,103 ---- } strcpy (buf, name); strcat (buf, slashDotXauthority + (name[1] == ' [That's all I got - presumably _XUnlockMutex was added here.]
The proposed fix looks fine (assuming the addition of unlock) for client side code - but are _XLockMutex, etal. defined in the X server?
nope, it's not. we need to find a better solution to this, long-term.
Sorry about the phenomenal bug spam, guys. Adding xorg-team@ to the QA contact so bugs don't get lost in future.
I just stumbled upon this. Wow. Is this still true, or has it been addressed and the bug just never got closed?
Mass closure: This bug has been untouched for more than six years, and is not obviously still valid. Please reopen this bug or file a new report if you continue to experience issues with current releases.
Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.