This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: PATCH: Eliminate uses of "sleep" in V3 testsuite
Paolo Carlini wrote:
Mark Mitchell wrote:
I checked in the attached patch, after making sure that the tests
still pass.
Sorry, Mark, but I'm noticing only now that you are adding naked throw
(instead
of __throw_exception_again) to testsuite_hooks.cc, which we carefully
avoid: try
building the library passing -fno-exceptions...
Fixed thusly.
What started we down this path was the discovery that
27_io/basic_filebuf/open/char/9507.cc sometimes hangs on HP-UX. The
parent process exits with code zero, but the child process hangs around.
(This problem predates my recent patches.)
I've now figured out where the race condition is. The parent calls
fbuf.open with std::ios_base::in and std::ios_base::out set. That
results in a call to open with O_RDWR. Then, the parent does a seek,
which fails, and therefore closes the descriptor. The child process
calls open with O_RDONLY. It will therefore block until/unless the
descriptor is open for writing. There is a narrow window in the parent
during which that is true, but if that windows passes before the child
calls open, we lose.
I can't fix this with the semaphore objects because the synchronization
would need to occur in the body of fbuf.open.
The call in the parent is not POSIX compliant, but on GNU/Linux (and
HP-UX, it seems) it's OK to open a FIFO for reading and writing
simultaneously. Given that, the child doesn't seem to be doing anything
useful, except perhaps testing that fbuf.sgetc() will not block on a
FIFO that has been opened, but is now closed.
Before Zack's changes
(http://gcc.gnu.org/ml/libstdc++/2004-02/msg00015.html), the parent used
O_WRONLY, which made the child process necessary. There was also no
race condition before Zack's changes, because the call in the parent
would block until the call in the child completed.
So, Zack avoided the problem that the HP-UX kernel refuses to open a
FIFO with O_WRONLY | O_TRUNC, but now we have a race condition. I think
that the best solution is to remove the child process. Thoughts?
--
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com
(916) 791-8304
2005-01-03 Mark Mitchell <mark@codesourcery.com>
* testsuite/testsuite_hooks.cc: Use __throw_exception_again
instead of just throw.
Index: testsuite_hooks.cc
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/testsuite/testsuite_hooks.cc,v
retrieving revision 1.25
diff -c -5 -p -r1.25 testsuite_hooks.cc
*** testsuite_hooks.cc 4 Jan 2005 00:17:11 -0000 1.25
--- testsuite_hooks.cc 4 Jan 2005 01:44:27 -0000
*************** namespace __gnu_test
*** 294,310 ****
#endif
// Get a semaphore set with one semaphore.
sem_set_ = semget(IPC_PRIVATE, 1, SEM_R | SEM_A);
if (sem_set_ == -1)
! throw std::runtime_error ("could not obtain semaphore set");
// Initialize the semaphore.
union semun val;
val.val = 0;
if (semctl(sem_set_, 0, SETVAL, val) == -1)
! throw std::runtime_error("could not initialize semaphore");
#else
// There are no semaphores on this system. We have no way to mark
// a test as "unsupported" at runtime, so we just exit, pretending
// that the test passed.
exit(0);
--- 294,312 ----
#endif
// Get a semaphore set with one semaphore.
sem_set_ = semget(IPC_PRIVATE, 1, SEM_R | SEM_A);
if (sem_set_ == -1)
! __throw_exception_again
! std::runtime_error ("could not obtain semaphore set");
// Initialize the semaphore.
union semun val;
val.val = 0;
if (semctl(sem_set_, 0, SETVAL, val) == -1)
! __throw_exception_again
! std::runtime_error("could not initialize semaphore");
#else
// There are no semaphores on this system. We have no way to mark
// a test as "unsupported" at runtime, so we just exit, pretending
// that the test passed.
exit(0);
*************** namespace __gnu_test
*** 325,346 ****
#ifdef _GLIBCXX_SYSV_SEM
struct sembuf op[1] = {
{ 0, 1, 0 }
};
if (semop(sem_set_, op, 1) == -1)
! throw std::runtime_error("could not signal semaphore");
#endif
}
void
semaphore::wait() {
#ifdef _GLIBCXX_SYSV_SEM
struct sembuf op[1] = {
{ 0, -1, SEM_UNDO }
};
if (semop(sem_set_, op, 1) == -1)
! throw std::runtime_error("could not wait for semaphore");
#endif
}
}; // namespace __gnu_test
namespace std
--- 327,350 ----
#ifdef _GLIBCXX_SYSV_SEM
struct sembuf op[1] = {
{ 0, 1, 0 }
};
if (semop(sem_set_, op, 1) == -1)
! __throw_exception_again
! std::runtime_error("could not signal semaphore");
#endif
}
void
semaphore::wait() {
#ifdef _GLIBCXX_SYSV_SEM
struct sembuf op[1] = {
{ 0, -1, SEM_UNDO }
};
if (semop(sem_set_, op, 1) == -1)
! __throw_exception_again
! std::runtime_error("could not wait for semaphore");
#endif
}
}; // namespace __gnu_test
namespace std