Skip to content

Commit 9182f02

Browse files
authored
fix: Multithread usage of SyncedEnforcer::Enforce (#227)
1 parent e1a81e2 commit 9182f02

File tree

4 files changed

+448
-171
lines changed

4 files changed

+448
-171
lines changed

casbin/enforcer_synced.cpp

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -170,55 +170,71 @@ void SyncedEnforcer ::LoadFilteredPolicy(Filter f) {
170170

171171
// SavePolicy saves the current policy (usually after changed with Casbin API) back to file/database.
172172
void SyncedEnforcer ::SavePolicy() {
173-
std::shared_lock<std::shared_mutex> lock(policyMutex);
173+
std::unique_lock<std::shared_mutex> lock(policyMutex);
174174
Enforcer::SavePolicy();
175175
}
176176

177177
// BuildRoleLinks manually rebuild the role inheritance relations.
178178
void SyncedEnforcer ::BuildRoleLinks() {
179-
std::shared_lock<std::shared_mutex> lock(policyMutex);
179+
std::unique_lock<std::shared_mutex> lock(policyMutex);
180180
Enforcer::BuildRoleLinks();
181181
}
182182

183183
// Enforce decides whether a "subject" can access a "object" with the operation "action", input parameters are usually: (sub, obj, act).
184184
bool SyncedEnforcer ::Enforce(std::shared_ptr<IEvaluator> evalator) {
185-
std::shared_lock<std::shared_mutex> lock(policyMutex);
185+
std::unique_lock<std::shared_mutex> lock(policyMutex);
186186
return Enforcer::Enforce(evalator);
187187
}
188188

189189
// Enforce with a vector param,decides whether a "subject" can access a
190190
// "object" with the operation "action", input parameters are usually: (sub,
191191
// obj, act).
192192
bool SyncedEnforcer::Enforce(const DataVector& params) {
193-
std::shared_lock<std::shared_mutex> lock(policyMutex);
193+
std::unique_lock<std::shared_mutex> lock(policyMutex);
194194
return Enforcer::Enforce(params);
195195
}
196196

197197
// Enforce with a vector param,decides whether a "subject" can access a
198198
// "object" with the operation "action", input parameters are usually: (sub,
199199
// obj, act).
200200
bool SyncedEnforcer ::Enforce(const DataList& params) {
201-
std::shared_lock<std::shared_mutex> lock(policyMutex);
201+
std::unique_lock<std::shared_mutex> lock(policyMutex);
202202
return Enforcer::Enforce(params);
203203
}
204204

205205
// Enforce with a map param,decides whether a "subject" can access a "object"
206206
// with the operation "action", input parameters are usually: (sub, obj, act).
207207
bool SyncedEnforcer ::Enforce(const DataMap& params) {
208-
std::shared_lock<std::shared_mutex> lock(policyMutex);
208+
std::unique_lock<std::shared_mutex> lock(policyMutex);
209209
return Enforcer::Enforce(params);
210210
}
211211

212212
// BatchEnforce enforce in batches
213213
std::vector<bool> SyncedEnforcer ::BatchEnforce(const std::initializer_list<DataList>& requests) {
214-
std::shared_lock<std::shared_mutex> lock(policyMutex);
215-
return Enforcer::BatchEnforce(requests);
214+
std::unique_lock<std::shared_mutex> lock(policyMutex);
215+
216+
// note: why not return Enforcer::BatchEnforce(requests) ?
217+
// Inside Enforcer::BatchEnforce, this->Enforce will be executed
218+
// but now 'this' is SyncedEnforcer, which means it will call SyncedEnforcer::Enforce
219+
// This will cause a deadlock
220+
221+
std::vector<bool> results;
222+
results.reserve(requests.size());
223+
for (const auto& request : requests) {
224+
results.push_back(Enforcer::Enforce(request));
225+
}
226+
return results;
216227
}
217228

218229
// BatchEnforceWithMatcher enforce with matcher in batches
219230
std::vector<bool> SyncedEnforcer::BatchEnforceWithMatcher(const std::string& matcher, const std::initializer_list<DataList>& requests) {
220-
std::shared_lock<std::shared_mutex> lock(policyMutex);
221-
return Enforcer::BatchEnforceWithMatcher(matcher, requests);
231+
std::unique_lock<std::shared_mutex> lock(policyMutex);
232+
std::vector<bool> results;
233+
results.reserve(requests.size());
234+
for (const auto& request : requests) {
235+
results.push_back(Enforcer::EnforceWithMatcher(matcher, request));
236+
}
237+
return results;
222238
}
223239

224240
// GetAllSubjects gets the list of subjects that show up in the current policy.

0 commit comments

Comments
 (0)