This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ 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: 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

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