This is the mail archive of the cygwin mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: 1.5.19: changes have broken Qt3


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Brian Dessent schrieb:
> [ 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.

If you take a look on assembler level you will find two constructors and
the breakpoint is set to the wrong one
0x610ad520 <_ZN17pthread_mutexattrC2Ev+0>:      push   %ebp
0x610ad560 <_ZN17pthread_mutexattrC1Ev+0>:      push   %ebp

(gdb) b pthread_mutexattr::pthread_mutexattr()
Breakpoint 3 at 0x610ad52c: -> _ZN17pthread_mutexattrC2Ev

but called is the other one.

0x610b0f7b <pthread_mutexattr_init+123>:        mov    %eax,(%esp)
0x610b0f7e <pthread_mutexattr_init+126>:        mov    %eax,%ebx
0x610b0f80 <pthread_mutexattr_init+128>:        call   0x610ad560
<_ZN17pthread_mutexattrC1Ev>


> 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.

Thanks for taking this time to write the detailed informations. Many
irritations came from the problems gdb had made. It would be good to
have a gdb update. :-)
Using the testcases in cvs src/winsup/testsuite/ I've verifyed by myself
that this stuff seems to work for that simple cases (although I have
still problem with threading stuff relating to qt3, more below).

There is only one case where I still believe that there may be a problem.
If a pthread_mutexattr_t is constructed on the stack and the magic class
membere is be exactly the predefined value, pthread_mutexattr_init()
will return EBUSY, although there is no good object, it is only by random.

Because of this in the former code of pthread_mutexattr_init()
check_valid_pointer() is used to check only the pointer, not the magic
class member. You and others may come to the conclusion that this could
be neglected, but it has to be listed.

Now i have still the problem why this thread was initial opened.
qt3 designer from the qt3-bin packages (and uic) crashes.
 The initial performed strace shows that there are internal recursive
exceptions until the stack overflows, which produces the 70% log amount
in http://cygwin.com/ml/cygwin/2006-05/msg00644.html.

If someone will try: it is reproducable using gdb /usr/lib/qt3/bin/designer

I found initial out that my initial patch prevents the segfault in
verifyable_object_isvalid() perfoming  ((*object)->magic != magic) and
let designer run.

The only workaround i currently have is to disable the first
is_good_object() call in pthread_mutexattr_init().

My currently conclusion is that there are rare conditions in the pthread
and/or exception stuff, which corrupts the stack and that there is more
work required to find out the problem.

May be I'm able to find out a bit more in the next time.

Regards
Ralf







-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.0 (Cygwin)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQFEeLXToHh+5t8EXncRApU9AJ41mBDC8gfCCy2Cvjz1sZoGUoop+wCgi0ny
V9l1sNE39vtWvqBHIjyMwHY=
=QQi3
-----END PGP SIGNATURE-----

--
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/


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]