-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: add lock for enif_send synchronization #19
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -78,17 +78,17 @@ erlfdb_future_cb(FDBFuture* fdb_future, void* data) | |
ERL_NIF_TERM msg; | ||
bool cancelled; | ||
|
||
|
||
enif_mutex_lock(future->lock); | ||
enif_mutex_lock(future->cancel_lock); | ||
cancelled = future->cancelled; | ||
enif_mutex_unlock(future->lock); | ||
enif_mutex_unlock(future->cancel_lock); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. if we want to prevent duplicated message sending below, we should take the locker longer. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please look at a newer version 😅: #20 |
||
|
||
if(!cancelled) { | ||
enif_mutex_lock(future->msg_lock); | ||
msg = T2(future->msg_env, future->msg_ref, ATOM_ready); | ||
enif_send(NULL, &(future->pid), future->msg_env, msg); | ||
enif_mutex_unlock(future->msg_lock); | ||
} | ||
Comment on lines
85
to
90
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is buggy, see erlang/otp#8358 (comment) and the following comments. Both the part about not passing There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @jhogberg really appreciated for your comments! We are stuck here, for what to set for the However as you mentioned in erlang/otp#8358 (comment), it is tricky to handle the sync callback from the 3rd party which is executed by beam managed scheduler thread. In the PR https://github.com/emqx/couchdb-erlfdb/pull/18/files#diff-ceadfa165520612e5b6b1a255f7680bcaa9e2a67bf47677f6884fd1db3cb03f5L122 it tried to fix the issue of reusing the as I see you propose following:
Do you mean we could use "process independent environments " ? We are a bit unsure about that because it was not stated in the doc about
BTW I look into the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, I mean using That will ensure that the process-bound/callback environment is passed when running on a BEAM-managed thread, and NULL otherwise. :-) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is the process-bound env safe to pass here? what if the process is dead or moved to other scheduler thread? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The process-bound or callback environment is guaranteed to be safe to use until its corresponding NIF or NIF callback returns. Thus, if you always set the environment through When |
||
|
||
|
||
// We're now done with this future which means we need | ||
// to release our handle to it. See erlfdb_create_future | ||
// for more on why this happens here. | ||
|
@@ -107,14 +107,19 @@ erlfdb_create_future(ErlNifEnv* env, FDBFuture* future, ErlFDBFutureGetter gette | |
ERL_NIF_TERM ret; | ||
fdb_error_t err; | ||
|
||
// TODO: check results of each operation. | ||
// TODO: return error if any operation fails and clean previously allocated resources. | ||
|
||
f = enif_alloc_resource(ErlFDBFutureRes, sizeof(ErlFDBFuture)); | ||
f->future = future; | ||
f->fgetter = getter; | ||
enif_self(env, &(f->pid)); | ||
f->msg_env = enif_alloc_env(); | ||
f->msg_ref = enif_make_copy(f->msg_env, ref); | ||
f->lock = enif_mutex_create("fdb:future_lock"); | ||
f->msg_lock = enif_mutex_create("fdb:future_msg_lock"); | ||
|
||
f->cancelled = false; | ||
f->cancel_lock = enif_mutex_create("fdb:future_cancel_lock"); | ||
|
||
// This resource reference counting dance is a bit | ||
// awkward as erlfdb_future_cb can be called both | ||
|
@@ -557,10 +562,10 @@ erlfdb_future_cancel(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) | |
} | ||
future = (ErlFDBFuture*) res; | ||
|
||
enif_mutex_lock(future->lock); | ||
enif_mutex_lock(future->cancel_lock); | ||
|
||
future->cancelled = true; | ||
enif_mutex_unlock(future->lock); | ||
enif_mutex_unlock(future->cancel_lock); | ||
|
||
fdb_future_cancel(future->future); | ||
|
||
|
@@ -589,11 +594,11 @@ erlfdb_future_silence(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) | |
} | ||
future = (ErlFDBFuture*) res; | ||
|
||
enif_mutex_lock(future->lock); | ||
enif_mutex_lock(future->cancel_lock); | ||
|
||
future->cancelled = true; | ||
|
||
enif_mutex_unlock(future->lock); | ||
enif_mutex_unlock(future->cancel_lock); | ||
|
||
return ATOM_ok; | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if we want to prevent duplicated message sending below, we should take the locker longer.