Bug 7588 - libXau is not thread safe
Summary: libXau is not thread safe
Status: NEW
Alias: None
Product: xorg
Classification: Unclassified
Component: Lib/Xau (show other bugs)
Version: git
Hardware: All All
: high major
Assignee: Xorg Project Team
QA Contact: Xorg Project Team
URL:
Whiteboard: 2011BRB_Reviewed
Keywords: love
Depends on:
Blocks:
 
Reported: 2006-07-21 09:47 UTC by Alan Coopersmith
Modified: 2011-10-02 02:26 UTC (History)
1 user (show)

See Also:
i915 platform:
i915 features:


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 Sequoia 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?


Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct.