Bug 7588 - libXau is not thread safe
libXau is not thread safe
Status: NEW
Product: xorg
Classification: Unclassified
Component: Lib/Xau
git
All All
: high major
Assigned To: Xorg Project Team
Xorg Project Team
2011BRB_Reviewed
: love
Depends on:
Blocks:
  Show dependency treegraph
 
Reported: 2006-07-21 09:47 UTC by Alan Coopersmith
Modified: 2011-10-02 02:26 UTC (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Alan Coopersmith 2006-07-21 09:47:02 UTC
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.]
Comment 1 Alan Coopersmith 2006-07-21 09:48:31 UTC
The proposed fix looks fine (assuming the addition of unlock) for client side
code - but are _XLockMutex, etal. defined in the X server?
Comment 2 Daniel Stone 2006-12-16 09:47:29 UTC
nope, it's not.  we need to find a better solution to this, long-term.
Comment 3 Daniel Stone 2007-02-27 01:32:58 UTC
Sorry about the phenomenal bug spam, guys.  Adding xorg-team@ to the QA contact so bugs don't get lost in future.
Comment 4 Jeremy Huddleston 2011-10-02 02:26:00 UTC
I just stumbled upon this.  Wow.  Is this still true, or has it been addressed 
and the bug just never got closed?