This is the mail archive of the
cygwin
mailing list for the Cygwin project.
Re: 1.5.19: changes have broken Qt3
[ 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/