Re: [Bug libstdc++/62313] Data race in debug iterators

2014-10-01 Thread Jonathan Wakely

On 30/09/14 22:18 +0200, François Dumont wrote:

Hi

   I prefer to submit this patch to you cause I am not very 
comfortable with Python stuff.


   I simply rely on Python cast feature. It doesn't really matter but 
is it going to simply consider the debug iterator as a normal one or 


Yes.

is it going through the C++ explicit cast operator on debug iterators 
?


No, it doesn't call any C++ function.

(N.B. I was searching in debug/safe_iterator.h for the 'explicit'
conversion operator you referred to and was confused because I
couldn't find it, which is because the operator for converting to base
is not 'explicit')

I'm not sure why the existing Python code does .cast(itype) when
_M_current is already that type, that seems unnecessary to me, but
I think your fix is correct and OK to commit, thanks.


Re: [Bug libstdc++/62313] Data race in debug iterators

2014-09-30 Thread Jonathan Wakely

On 26/09/14 11:05 +0100, Jonathan Wakely wrote:

On 26/09/14 00:00 +0200, François Dumont wrote:



Apart from those minor adjustments I think this looks good, but I'd
like to know that it has been tested with -fsanitize=thread, even if
only lightly tested.




Hi

  Dmitry, who reported the bug, confirmed the fix. Can I go ahead 
and commit ?


Yes, OK.


This caused some failures in the printer tests:

Running
/home/jwakely/src/gcc/gcc/libstdc++-v3/testsuite/libstdc++-prettyprinters/prettyprinters.exp
 ...
FAIL: libstdc++-prettyprinters/debug.cc print deqiter
FAIL: libstdc++-prettyprinters/debug.cc print lstiter
FAIL: libstdc++-prettyprinters/debug.cc print lstciter
FAIL: libstdc++-prettyprinters/debug.cc print mpiter
FAIL: libstdc++-prettyprinters/debug.cc print spciter



Re: [Bug libstdc++/62313] Data race in debug iterators

2014-09-30 Thread François Dumont

I forgot to check pretty printer tests indeed, I will.

François

On 30/09/2014 17:32, Jonathan Wakely wrote:

On 26/09/14 11:05 +0100, Jonathan Wakely wrote:

On 26/09/14 00:00 +0200, François Dumont wrote:



Apart from those minor adjustments I think this looks good, but I'd
like to know that it has been tested with -fsanitize=thread, even if
only lightly tested.




Hi

  Dmitry, who reported the bug, confirmed the fix. Can I go ahead 
and commit ?


Yes, OK.


This caused some failures in the printer tests:

Running
/home/jwakely/src/gcc/gcc/libstdc++-v3/testsuite/libstdc++-prettyprinters/prettyprinters.exp 
...

FAIL: libstdc++-prettyprinters/debug.cc print deqiter
FAIL: libstdc++-prettyprinters/debug.cc print lstiter
FAIL: libstdc++-prettyprinters/debug.cc print lstciter
FAIL: libstdc++-prettyprinters/debug.cc print mpiter
FAIL: libstdc++-prettyprinters/debug.cc print spciter






Re: [Bug libstdc++/62313] Data race in debug iterators

2014-09-30 Thread François Dumont

Hi

I prefer to submit this patch to you cause I am not very 
comfortable with Python stuff.


I simply rely on Python cast feature. It doesn't really matter but 
is it going to simply consider the debug iterator as a normal one or is 
it going through the C++ explicit cast operator on debug iterators ?


François


On 30/09/2014 17:32, Jonathan Wakely wrote:

On 26/09/14 11:05 +0100, Jonathan Wakely wrote:

On 26/09/14 00:00 +0200, François Dumont wrote:



Apart from those minor adjustments I think this looks good, but I'd
like to know that it has been tested with -fsanitize=thread, even if
only lightly tested.




Hi

  Dmitry, who reported the bug, confirmed the fix. Can I go ahead 
and commit ?


Yes, OK.


This caused some failures in the printer tests:

Running
/home/jwakely/src/gcc/gcc/libstdc++-v3/testsuite/libstdc++-prettyprinters/prettyprinters.exp 
...

FAIL: libstdc++-prettyprinters/debug.cc print deqiter
FAIL: libstdc++-prettyprinters/debug.cc print lstiter
FAIL: libstdc++-prettyprinters/debug.cc print lstciter
FAIL: libstdc++-prettyprinters/debug.cc print mpiter
FAIL: libstdc++-prettyprinters/debug.cc print spciter




Index: python/libstdcxx/v6/printers.py
===
--- python/libstdcxx/v6/printers.py	(revision 215741)
+++ python/libstdcxx/v6/printers.py	(working copy)
@@ -460,7 +460,7 @@
 # and return the wrapped iterator value.
 def to_string (self):
 itype = self.val.type.template_argument(0)
-return self.val['_M_current'].cast(itype)
+return self.val.cast(itype)
 
 class StdMapPrinter:
 Print a std::map or std::multimap


Re: [Bug libstdc++/62313] Data race in debug iterators

2014-09-26 Thread Jonathan Wakely

On 26/09/14 00:00 +0200, François Dumont wrote:



Apart from those minor adjustments I think this looks good, but I'd
like to know that it has been tested with -fsanitize=thread, even if
only lightly tested.




Hi

   Dmitry, who reported the bug, confirmed the fix. Can I go ahead 
and commit ?


Yes, OK.


Re: [Bug libstdc++/62313] Data race in debug iterators

2014-09-25 Thread François Dumont



Apart from those minor adjustments I think this looks good, but I'd
like to know that it has been tested with -fsanitize=thread, even if
only lightly tested.




Hi

Dmitry, who reported the bug, confirmed the fix. Can I go ahead and 
commit ?


François


Re: [Bug libstdc++/62313] Data race in debug iterators

2014-09-23 Thread François Dumont

On 22/09/2014 00:04, Jonathan Wakely wrote:

On 10/09/14 22:55 +0200, François Dumont wrote:

Hi

   Here is a proposal to fix this data race issue.

   I finally generalized bitset approach to fix it by inheriting from 
the normal iterator first and then the _Safe_iterator_base type. None 
of the libstdc++ iterator types are final so it is fine. 
Surprisingly, despite inheritance being private gcc got confused 
between _Safe_iterator_base _M_next and forward_list _M_next so I 
need to adapt some code to make usage of _Safe_iterator_base _M_next 
explicit.


Access control in C++ is not related to visibility, name lookup still
finds private members, but it is an error to use them.


Ok, tricky.



   I also consider any operator where normal iterator is being 
modified while the safe iterator is linked to the list of iterators. 
This is necessary to make sure that thread sanatizer won't consider a 
race condition. I didn't touch to bitset::reference because list 
references are only access on bitset destruction which is clearly not 
an operation allowed to do while playing with references in another 
thread.


   Do you see any way to check for this problem in the testsuite ? Is 
there a thread sanitizer we could use ?


GCC's -fsanitize=thread option, although using it in the testsuite
would need something like dg-require-tsan so the test doesn't run on
platforms where it doesn't work, or if GCC was built without
libsanitizer.

Have you run some tests using -fsanitize=thread, even if they are not
in the testsuite?


No I hadn't and try since but without success. When I build with 
-fsanitize=thread the produced binary just segfault at startup. It 
complained about using -fPIE at compilation time and -lpie at link time 
but even with those options it segfault. Don't know what is going wrong. 
Maybe Dmitry who reported the bug could give it a try. I will ask for 
this on the bug ticket





Index: include/debug/safe_iterator.h

Same renaming here please, to _Iter_base.

Apart from those minor adjustments I think this looks good, but I'd
like to know that it has been tested with -fsanitize=thread, even if
only lightly tested.




I fixed the vocabulary problems. Just need a slight test then.

François


Re: [Bug libstdc++/62313] Data race in debug iterators

2014-09-23 Thread Marek Polacek
On Tue, Sep 23, 2014 at 10:42:31PM +0200, François Dumont wrote:
 No I hadn't and try since but without success. When I build with
 -fsanitize=thread the produced binary just segfault at startup. It
 complained about using -fPIE at compilation time and -lpie at link time but
 even with those options it segfault. Don't know what is going wrong. Maybe

At link time it should be -pie, not -lpie.

Marek


Re: [Bug libstdc++/62313] Data race in debug iterators

2014-09-21 Thread Jonathan Wakely

On 10/09/14 22:55 +0200, François Dumont wrote:

Hi

   Here is a proposal to fix this data race issue.

   I finally generalized bitset approach to fix it by inheriting from 
the normal iterator first and then the _Safe_iterator_base type. None 
of the libstdc++ iterator types are final so it is fine. Surprisingly, 
despite inheritance being private gcc got confused between 
_Safe_iterator_base _M_next and forward_list _M_next so I need to 
adapt some code to make usage of _Safe_iterator_base _M_next explicit.


Access control in C++ is not related to visibility, name lookup still
finds private members, but it is an error to use them.

   I also consider any operator where normal iterator is being 
modified while the safe iterator is linked to the list of iterators. 
This is necessary to make sure that thread sanatizer won't consider a 
race condition. I didn't touch to bitset::reference because list 
references are only access on bitset destruction which is clearly not 
an operation allowed to do while playing with references in another 
thread.


   Do you see any way to check for this problem in the testsuite ? Is 
there a thread sanitizer we could use ?


GCC's -fsanitize=thread option, although using it in the testsuite
would need something like dg-require-tsan so the test doesn't run on
platforms where it doesn't work, or if GCC was built without
libsanitizer.

Have you run some tests using -fsanitize=thread, even if they are not
in the testsuite?


Index: include/debug/safe_iterator.h
===
--- include/debug/safe_iterator.h   (revision 215134)
+++ include/debug/safe_iterator.h   (working copy)
@@ -109,16 +109,21 @@
   *  %_Safe_iterator has member functions for iterator invalidation,
   *  attaching/detaching the iterator from sequences, and querying
   *  the iterator's state.
+   *
+   *  Note that _Iterator must rely first in the type memory layout so that it


I can't parse this ... maybe _Iterator must be the first base class ?


+   *  gets initialized before the iterator is being attached to the container


s/container/container's/


+   *  list of iterators and it is being dettached before _Iterator get


s/dettached/detached/


+   *  destroy. Otherwise it would result in a data race.


s/destroy/destroyed/


   */
  templatetypename _Iterator, typename _Sequence
-class _Safe_iterator : public _Safe_iterator_base
+class _Safe_iterator
+: private _Iterator,
+  public _Safe_iterator_base
{
-  typedef _Safe_iterator _Self;
+  typedef _Iterator _Ite_base;


Please rename this to _Iter_base, iter is a more conventional
abbreviation than ite


@@ -388,28 +433,27 @@
  /**
   * @brief Return the underlying iterator
   */
-  _Iterator
-  base() const _GLIBCXX_NOEXCEPT { return _M_current; }
+  _Iterator
+  base() _GLIBCXX_NOEXCEPT { return *this; }

+  const _Iterator
+  base() const _GLIBCXX_NOEXCEPT { return *this; }


I suppose base() doesn't need to be uglified to _M_base, because all
the containers already use std::reverse_iterator which uses the name
base.


Index: include/debug/safe_local_iterator.h
===
--- include/debug/safe_local_iterator.h (revision 215134)
+++ include/debug/safe_local_iterator.h (working copy)
@@ -49,15 +49,15 @@
   *  the iterator's state.
   */
  templatetypename _Iterator, typename _Sequence
-class _Safe_local_iterator : public _Safe_local_iterator_base
+class _Safe_local_iterator
+: private _Iterator
+, public _Safe_local_iterator_base
{
-  typedef _Safe_local_iterator _Self;
+  typedef _Iterator _Ite_base;


Same renaming here please, to _Iter_base.

Apart from those minor adjustments I think this looks good, but I'd
like to know that it has been tested with -fsanitize=thread, even if
only lightly tested.



[Bug libstdc++/62313] Data race in debug iterators

2014-09-10 Thread François Dumont

Hi

Here is a proposal to fix this data race issue.

I finally generalized bitset approach to fix it by inheriting from 
the normal iterator first and then the _Safe_iterator_base type. None of 
the libstdc++ iterator types are final so it is fine. Surprisingly, 
despite inheritance being private gcc got confused between 
_Safe_iterator_base _M_next and forward_list _M_next so I need to adapt 
some code to make usage of _Safe_iterator_base _M_next explicit.


I also consider any operator where normal iterator is being 
modified while the safe iterator is linked to the list of iterators. 
This is necessary to make sure that thread sanatizer won't consider a 
race condition. I didn't touch to bitset::reference because list 
references are only access on bitset destruction which is clearly not an 
operation allowed to do while playing with references in another thread.


Do you see any way to check for this problem in the testsuite ? Is 
there a thread sanitizer we could use ?


2014-09-10  François Dumont  fdum...@gcc.gnu.org

PR libstdc++/62313
* include/debug/safe_base.h
(_Safe_iterator_base(const _Safe_iterator_base)): Delete declaration.
(_Safe_iterator_base operator=(const _Safe_iterator_base)): Likewise.
* include/debug/safe_iterator.h (_Safe_iterator): Move normal 
iterator
before _Safe_iterator_base in memory. Lock before modifying the 
iterator

in numerous places.
* include/debug/safe_local_iterator.h
(_Safe_local_iterator_base(const _Safe_local_iterator_base)): Delete
declaration.
(_Safe_local_iterator_base operator=(const 
_Safe_local_iterator_base)):

Likewise.
* include/debug/safe_unordered_base.h (_Safe_local_iterator):  Move
normal iterator before _Safe_iterator_base in memory. Lock before
modifying the iterator in numerous places.
* include/debug/forward_list (_Safe_forward_list::_M_swap_aux): 
Adapt.

* include/debug/safe_sequence.tcc
(_Safe_sequence::_M_transfer_from_if): Adapt.

Tested under Linux x86_64 debug mode.

Ok to commit ?

François
Index: include/debug/forward_list
===
--- include/debug/forward_list	(revision 215134)
+++ include/debug/forward_list	(working copy)
@@ -86,24 +86,26 @@
   for (_Safe_iterator_base* __iter = __lhs_iterators; __iter;)
 	{
 	  // Even iterator is cast to const_iterator, not a problem.
-	  const_iterator* __victim = static_castconst_iterator*(__iter);
+	  _Safe_iterator_base* __victim_base = __iter;
+	  const_iterator* __victim =
+	static_castconst_iterator*(__victim_base);
 	  __iter = __iter-_M_next;
 	  if (__victim-base() == __rseq._M_base().cbefore_begin())
 	{
 	  __victim-_M_unlink();
-	  if (__lhs_iterators == __victim)
-		__lhs_iterators = __victim-_M_next;
+	  if (__lhs_iterators == __victim_base)
+		__lhs_iterators = __victim_base-_M_next;
 	  if (__bbegin_its)
 		{
-		  __victim-_M_next = __bbegin_its;
-		  __bbegin_its-_M_prior = __victim;
+		  __victim_base-_M_next = __bbegin_its;
+		  __bbegin_its-_M_prior = __victim_base;
 		}
 	  else
-		__last_bbegin = __victim;
-	  __bbegin_its = __victim;
+		__last_bbegin = __victim_base;
+	  __bbegin_its = __victim_base;
 	}
 	  else
-	__victim-_M_sequence = __lhs;
+	__victim_base-_M_sequence = __lhs;
 	}
 
   if (__bbegin_its)
Index: include/debug/safe_base.h
===
--- include/debug/safe_base.h	(revision 215134)
+++ include/debug/safe_base.h	(working copy)
@@ -95,12 +95,6 @@
 : _M_sequence(0), _M_version(0), _M_prior(0), _M_next(0)
 { this-_M_attach(__x._M_sequence, __constant); }
 
-_Safe_iterator_base
-operator=(const _Safe_iterator_base);
-
-explicit
-_Safe_iterator_base(const _Safe_iterator_base);
-
 ~_Safe_iterator_base() { this-_M_detach(); }
 
 /** For use in _Safe_iterator. */
Index: include/debug/safe_iterator.h
===
--- include/debug/safe_iterator.h	(revision 215134)
+++ include/debug/safe_iterator.h	(working copy)
@@ -109,16 +109,21 @@
*  %_Safe_iterator has member functions for iterator invalidation,
*  attaching/detaching the iterator from sequences, and querying
*  the iterator's state.
+   *
+   *  Note that _Iterator must rely first in the type memory layout so that it
+   *  gets initialized before the iterator is being attached to the container
+   *  list of iterators and it is being dettached before _Iterator get
+   *  destroy. Otherwise it would result in a data race.
*/
   templatetypename _Iterator, typename _Sequence
-class _Safe_iterator : public _Safe_iterator_base
+class _Safe_iterator
+: private _Iterator,
+  public _Safe_iterator_base
 {
-  typedef _Safe_iterator _Self;
+  typedef _Iterator _Ite_base;
+  typedef _Safe_iterator_base _Safe_base;
   typedef