[GitHub] zookeeper pull request #584: ZOOKEEPER-3102: Potential race condition when c...

2018-07-28 Thread maoling
Github user maoling commented on a diff in the pull request:

https://github.com/apache/zookeeper/pull/584#discussion_r205961633
  
--- Diff: src/java/main/org/apache/zookeeper/server/DataTree.java ---
@@ -478,7 +478,10 @@ public void createNode(final String path, byte data[], 
List acl,
 HashSet list = ephemerals.get(ephemeralOwner);
 if (list == null) {
 list = new HashSet();
-ephemerals.put(ephemeralOwner, list);
+HashSet _list;
+if ((_list = ephemerals.putIfAbsent(ephemeralOwner, 
list)) != null) {
+list = _list;
+}
 }
 synchronized (list) {
--- End diff --

@anmolnar 
I will test it with that unit test , using a 'threadpool' and create 
100 nodes to reproduce what I guess。
I wish I was wrong,but if i'm right ,you need to watch Breaking Bad series 
(smirk).




---


[GitHub] zookeeper pull request #584: ZOOKEEPER-3102: Potential race condition when c...

2018-07-28 Thread breed
Github user breed commented on a diff in the pull request:

https://github.com/apache/zookeeper/pull/584#discussion_r205959572
  
--- Diff: src/java/main/org/apache/zookeeper/server/DataTree.java ---
@@ -478,7 +478,10 @@ public void createNode(final String path, byte data[], 
List acl,
 HashSet list = ephemerals.get(ephemeralOwner);
 if (list == null) {
 list = new HashSet();
-ephemerals.put(ephemeralOwner, list);
+HashSet _list;
--- End diff --

we need synchronization to prevent znode changes while the znode is being 
snapshot to disk, but for request processing there is only a single thread that 
does mutations and mutations don't happen while read requests are being 
processed.


---


[GitHub] zookeeper pull request #584: ZOOKEEPER-3102: Potential race condition when c...

2018-07-28 Thread anmolnar
Github user anmolnar commented on a diff in the pull request:

https://github.com/apache/zookeeper/pull/584#discussion_r205950078
  
--- Diff: src/java/main/org/apache/zookeeper/server/DataTree.java ---
@@ -478,7 +478,10 @@ public void createNode(final String path, byte data[], 
List acl,
 HashSet list = ephemerals.get(ephemeralOwner);
 if (list == null) {
 list = new HashSet();
-ephemerals.put(ephemeralOwner, list);
+HashSet _list;
+if ((_list = ephemerals.putIfAbsent(ephemeralOwner, 
list)) != null) {
+list = _list;
+}
 }
 synchronized (list) {
--- End diff --

I'm not sure about that.

ephemerals.putIfAbsent() is thread safe: it guarantees that newly created 
instance will be added to the HashMap only if the key is associated with a null 
value. Otherwise you will get the instance already present in the HashMap.
Either case `list` will point to the one and only instance present in the 
hashmap.

In your example when Step2 enters L483 it will get back the instance which 
was created and added to the HashMap by Step1 before it acquired the `list` 
lock. And that instance cannot be replaced in the HashMap with this code.

After all `synchronized (list)` only guards access to the List, HashMap is 
guarded by putIfAbsent().
I still believe that `computeIfAbsent()` is more convenient and readable 
here.


---


[GitHub] zookeeper pull request #584: ZOOKEEPER-3102: Potential race condition when c...

2018-07-28 Thread maoling
Github user maoling commented on a diff in the pull request:

https://github.com/apache/zookeeper/pull/584#discussion_r205941687
  
--- Diff: src/java/main/org/apache/zookeeper/server/DataTree.java ---
@@ -478,7 +478,10 @@ public void createNode(final String path, byte data[], 
List acl,
 HashSet list = ephemerals.get(ephemeralOwner);
 if (list == null) {
 list = new HashSet();
-ephemerals.put(ephemeralOwner, list);
+HashSet _list;
+if ((_list = ephemerals.putIfAbsent(ephemeralOwner, 
list)) != null) {
+list = _list;
+}
 }
 synchronized (list) {
--- End diff --

Even if when `createNode` is called by multi-thread.this fix is also not 
thread-safe.
Step1:One thread has acquired the `list` lock and enters into L487,add a 
element into  `list`
Step2:But at the same time just after Step1, another thread enters into 
L483,the reference of `list` is pointed to the old `_list` object. It will 
cause thread-unsafe
BTW: **Breaking Bad** is the best U.S.TV series


---


[GitHub] zookeeper pull request #584: ZOOKEEPER-3102: Potential race condition when c...

2018-07-27 Thread anmolnar
Github user anmolnar commented on a diff in the pull request:

https://github.com/apache/zookeeper/pull/584#discussion_r205749086
  
--- Diff: src/java/main/org/apache/zookeeper/server/DataTree.java ---
@@ -478,7 +478,10 @@ public void createNode(final String path, byte data[], 
List acl,
 HashSet list = ephemerals.get(ephemeralOwner);
 if (list == null) {
 list = new HashSet();
-ephemerals.put(ephemeralOwner, list);
+HashSet _list;
--- End diff --

You can use `computeIfAbsent()` like this:
```java
HashSet list = ephemerals.computeIfAbsent(ephemeralOwner, k -> new 
HashSet());
```


---


[GitHub] zookeeper pull request #584: ZOOKEEPER-3102: Potential race condition when c...

2018-07-25 Thread MichaelScofield
GitHub user MichaelScofield opened a pull request:

https://github.com/apache/zookeeper/pull/584

ZOOKEEPER-3102: Potential race condition when create ephemeral nodes.



You can merge this pull request into a Git repository by running:

$ git pull https://github.com/MichaelScofield/zookeeper ZOOKEEPER-3102

Alternatively you can review and apply these changes as the patch at:

https://github.com/apache/zookeeper/pull/584.patch

To close this pull request, make a commit to your master/trunk branch
with (at least) the following in the commit message:

This closes #584


commit f7b494858e719b2c6dc08befea5bd2caf82c3976
Author: luo.fucong 
Date:   2018-07-26T04:46:24Z

ZOOKEEPER-3102: Potential race condition when create ephemeral nodes.




---