casbin / etcd-watcher

Etcd watcher for Casbin

Home Page:https://github.com/casbin/casbin

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

A small question about the data-racing problems in code

ComradeProgrammer opened this issue · comments

Actually, I have two questions.

Question 1 is that ,in watcher.go line 92, function SetUpdateCallback modifies the 'callback' attribute of Watcher, with any lock mechanism. However, in watcher.go line 131 we read attribute 'callback', without any lock mechanism, either. Considering that these two function is very possible to be executed in different goroutines, won't this cause a data race? I am really confused.

Question 2 is that, in watcher.go ,function Update, we read the specified key 'w,keyName'(at line 101) and soon write to this key (at line 120) basing on the value we got before, without any distributive lock mechanism.

In a hypothetical scenario, 
when this watcher is used by two seperate machines, 
and machine 1 executes to "Get", gets value "5",
and machine 2 executes to "Get",also gets value "5",
then machine 1 writes 6
and then machine 2 writes 6, too.

This will cause the key to store incorrect value, and may possibly cause machine 1 lose to a revision of config"6" generated by machine 2 .
Why we don't need to use a distributive lock here? I don't understand.

Looking forward to your reply.

@ComradeProgrammer use permalink:

image

@closetool @tangyang9464

@ComradeProgrammer OK, for your first question, SetCallBack function is designed to be called before the watcher's running stage, and we shouldn't call watcher after it is running. But adding a lock for it is not bad, I'll do it later.
For the second question, at line 120, we don't change the value of keyName. In watcher, keyName will not be changed after initialization, so it doesn't need to be protected.

For the second question, I think there is some misunderstandings. Sorry for my vague descriptions. I was actually talking about parallel modification to the value stored in etcd under key 'w.keyName' , rather than the value of ''w.keyName' in struct w.

Two watcher on different machines can still cause this problem, i think, because in function update , we read the value from the etcd

resp, err := w.client.Get(context.Background(), w.keyName)

, plus 1 to it , and then write it back
_, err = w.client.Put(context.TODO(), w.keyName, newRev)

. However, we have no mechanism to prevent watcher on a totally different computer from reading this value exactly when the former watcher has read the value but hasn't write the increment back yet.

🎉 This issue has been resolved in version 2.0.1 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

@ComradeProgrammer You are right, but that's not a data race problem. It's something about distribute system. In casbin watcher system, it is allowed.