X-Spam-Check-By: sourceware.org Message-ID: <44789FCB.2FFF9168@dessent.net> Date: Sat, 27 May 2006 11:51:55 -0700 From: Brian Dessent X-Mailer: Mozilla 4.79 [en] (Windows NT 5.0; U) MIME-Version: 1.0 To: Ralf Habacker CC: cygwin AT cygwin DOT com Subject: Re: 1.5.19: changes have broken Qt3 References: <044e01c67e8f$0abed720$a501a8c0 AT CAM DOT ARTIMI DOT COM> <447350C4 DOT 1080604 AT freenet DOT de> <20060523182326 DOT GB6138 AT trixie DOT casa DOT cgf DOT cx> <4473607C DOT 2070806 AT freenet DOT de> <44741E31 DOT 665A1B7 AT dessent DOT net> <447420D1 DOT 8090909 AT freenet DOT de> <4474250C DOT AA4A166 AT dessent DOT net> <44744F28 DOT 905 AT freenet DOT de> Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit X-IsSubscribed: yes Reply-To: cygwin AT cygwin DOT com Mailing-List: contact cygwin-help AT cygwin DOT com; run by ezmlm List-Subscribe: List-Archive: List-Post: List-Help: , Sender: cygwin-owner AT cygwin DOT com Mail-Followup-To: cygwin AT cygwin DOT com Delivered-To: mailing list cygwin AT cygwin DOT com [ I realized that a couple of points in this thread were never addressed -- we sort of got side tracked on the GDB issue. I just want to reply to these points and try to convince you that this bug you see does not exist. People have a tendency to point to the archives and say "lookee, it's broken" if the thread does not come to a result. ] Ralf Habacker wrote: > You said that the testcase runs, yes, but do you have tried to debug the > cygwin dll with this exception handling. Please start the above > mentioned testcase in gdb and enter > > b main > r > b pthread_mutexattr::pthread_mutexattr() > c > > This breakpoint is never reached (at least in released gdb) and makes it > hard to debug cygwin's threading stuff, probably impossible in this area. The breakpoint does not fire, correct. But that is because pthread_mutexattr's constructor is empty (other than the initialization list): pthread_mutexattr::pthread_mutexattr ():verifyable_object (PTHREAD_MUTEXATTR_MAGIC), pshared (PTHREAD_PROCESS_PRIVATE), mutextype (PTHREAD_MUTEX_ERRORCHECK) { } If instead you set a breakpoint for the desired line that calls the constructor (in this case, thread.cc:3027) then it does fire. And if you use a CVS GDB you get no spurious faults either. > This means to be able to debug the cygwin dll in this area I have to > recompile a special cygwin version with something like below mentioned.: > > /* FIXME: write and test process shared mutex's. */ > extern "C" int > pthread_mutexattr_init (pthread_mutexattr_t *attr) > > old: > if (pthread_mutexattr::is_good_object (attr)) > return EBUSY; > > new: > if (attr && pthread_mutexattr::is_good_object (attr)) > return EBUSY; This is totally useless. In order for "if (attr)" to be false, the function would have had to been called as pthread_mutexattr_init (NULL) rather than pthread_mutexattr_init (&some_as_yet_uninitialized_variable). Furthermore, if attr really were false, then the next line: *attr = new pthread_mutexattr (); would cause a NULL dereference which would not be caught, causing the program to crash and burn. The function must always be passed a valid pointer; the thing it points to might be uninitialized though. Let's walk through the complete series of events that happens in the testcase below: pthread_mutexattr_t mxAttr; assert(pthread_mutexattr_init(&mxAttr) == 0); This is the thing that you claim is broken, however if you run this testcase from a regular prompt (outside GDB) it does not assert, and in fact the mutexattr is correctly initialized. (And if you do run it in a recent GDB it does not assert nor fault either.) Let's look at the entire chain of code involved here: extern "C" int pthread_mutexattr_init (pthread_mutexattr_t *attr) { if (pthread_mutexattr::is_good_object (attr)) return EBUSY; *attr = new pthread_mutexattr (); if (!pthread_mutexattr::is_good_object (attr)) { delete (*attr); *attr = NULL; return ENOMEM; } return 0; } inline bool pthread_mutexattr::is_good_object (pthread_mutexattr_t const * attr) { if (verifyable_object_isvalid (attr, PTHREAD_MUTEXATTR_MAGIC) != VALID_OBJECT) return false; return true; } static inline verifyable_object_state verifyable_object_isvalid (void const * objectptr, long magic, void *static_ptr1, void *static_ptr2, void *static_ptr3) { verifyable_object **object = (verifyable_object **) objectptr; myfault efault; if (efault.faulted ()) return INVALID_OBJECT; if ((static_ptr1 && *object == static_ptr1) || (static_ptr2 && *object == static_ptr2) || (static_ptr3 && *object == static_ptr3)) return VALID_STATIC_OBJECT; if ((*object)->magic != magic) return INVALID_OBJECT; return VALID_OBJECT; } So, the call chain will look like this: pthread_mutexattr_init(&mxAttr) -> pthread_mutexattr::is_good_object (&mxAttr) -> verifyable_object_isvalid (&mxAttr, PTHREAD_MUTEXATTR_MAGIC, NULL,NULL,NULL) Of course, these last two functions will be expanded inline, so this will all occur in the context of pthread_mutexattr_init. We are at the point in verifyable_object_isvalid of: if ((*object)->magic != magic) Here, object is &mxAttr, so *object is mxAttr. But mxAttr is not yet initialized, so dereferencing it as mxAttr->magic causes a fault. This causes verifyable_object_isvalid to return INVALID_OBJECT through the "if (efault.faulted ())" branch. Consequently, the if() condition in pthread_mutexattr::is_good_object is true, the function returns false, the if() condition at the beginning of pthread_mutexattr_init is false, and execution continues to the line "*attr = new pthread_mutexattr ()", and finally mxAttr is initialized just as we desire. I hope that I have shown that even though a fault occurs that execution continues normally and the mutexattr IS initialized correctly. Brian -- Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple Problem reports: http://cygwin.com/problems.html Documentation: http://cygwin.com/docs.html FAQ: http://cygwin.com/faq/