Node.js: How to implement a simple and functional Mutex mechanism to avoid racing conditions that bypass the guard statement in simultaneous actions - node.js

In the following class, the _busy field acts as a semaphore; but, in "simultaneous" situations it fails to guard!
class Task {
_busy = false;
async run(s) {
try {
if (this._busy)
return;
this._busy = true;
await payload();
} finally {
this._busy = false;
}
}
}
The sole purpose of the run() is to execute the payload() exclusively, denying all the other invocations while it's still being carried on. In other words, when "any" of the invocations reach to to the run() method, I want it to only allow the first one to go through and lock it down (denying all the others) until it's done with its payload; "finally", it opens up once it's done.
In the implementation above, the racing condition do occur by invoking the run() method simultaneously through various parts of the app. Some of the invocations (more than 1) make it past through the "guarding" if statement, since none of them are yet reached to the this._busy = true to lock it down (they get past simultaneously). So, the current implementation doesn't cut it!
I just want to deny the simultaneous invocations while one of them is already being carried out. I'm looking for a simple solution to only resolve this issue. I've designated the async-mutex library as a last resort!
So, how to implement a simple "locking" mechanism to avoid racing conditions that bypass the guard statement in simultaneous actions?
For more clarification, as per the comments below, the following is almost the actual Task class (without the irrelevant).
class Task {
_cb;
_busy = false;
_count = 0;
constructor(cb) {
this._cb = cb;
}
async run(params = []) {
try {
if (this._busy)
return;
this._busy = true;
this._count++;
if (this._count > 1) {
console.log('Race condition!', 'count:', this._count);
this._count--;
return;
}
await this._cb(...params);
} catch (err) {
await someLoggingRoutine();
} finally {
this._busy = false;
this._count--;
}
}
}
I do encounter with the Race condition! log. Also, all the task instances are local to a simple driver file (the instances are not passed down to any other function, they only wander as local instances in a single function.) They are created in the following form:
const t1 = new Task(async () => { await doSth1(); /*...*/ });
const t2 = new Task(async () => { await doSth2(); /*...*/ });
const t3 = new Task(async () => { await doSth3(); /*...*/ });
// ...
I do call them in the various library events, some of which happen concurrently and causing the "race condition" issue; e.g.:
someLib.on('some-event', async function() { /*...*/ t1.run().then(); /*...*/ });
anotherLib.on('event-2', async function() { /*...*/ t1.run().then(); /*...*/ });

Oh god, now I see it. How could I have missed this so long! Here is your implemenation:
async run() {
try {
if (this._busy)
return;
...
} finally {
this._busy = false;
}
}
As per documentations:
The Statements in the finally block are executed before control flow exits the try...catch...finally construct. These statements execute regardless of whether an exception was thrown or caught.
Thus, when it's busy and the flow reaches the guarding if, and then, logically encounters the return statement. The return statement causes the flow to exit the try...catch...finally construct; thus, as per the documentations, the statements in the finally block are executed whatsoever: setting the this._busy = false;, opening the thing up!
So, the first call of run() sets this._busy as being true; then enters the critical section with its longrunning callback. While this callback is running, just another event causes the run() to be invoked. This second call is rationally blocked from entering the critical section by the guarding if statement:
if (this._busy) return;
Encountering the return statement to exit the function (and thus exiting the try...catch...finally construct) causes the statements in the finally block to be executed; thus, this._busy = false resets the flag, even though the first callback is still running! Now suppose a third call to the run() from yet another event is invoked! Since this._busy is just set to false, the flow happily enters the critical section again, even though the first callback is still running! In turn, it sets this._busy back to true. In the meantime, the first callback finishes, and reaches the finally block, where it set this._busy = false again; even though the other callback is still running. So the next call to run() can enter the critical section again with no problems... And so on and so forth...
So to resolve the issue, the check for the critical section should be outside of the try block:
async run() {
if (this._busy) return;
this._busy = true;
try { ... }
finally {
this._busy = false;
}
}

Related

Asynchronous MVC4 action seems to block multiple requests received at the same time

I'm trying to make my MVC controller action run asynchronously under .NET 4.0. However, none of my attempts have given me the results I want. I have the following action:
public ActionResult ImportXml()
{
try
{
if (_importRunning)
return Content("Already running");
var obj = new object();
lock (obj)
{
_importRunning = true;
Thread.Sleep(20000);
//_employesImportService.ImportXml();
_importRunning = false;
}
return Content("Done");
}
catch (Exception e)
{
return Content(e.Message);
}
}
When I run two browsers simultaneously that call this action, both seem to wait the 20 seconds I set in the Thread.Sleep(20000). I though that using the lock mechanism would block one request and return the "Already running" content immediately. I'm using .NET 4.0 and I don't have the option of using async await. But is there another way of implementing this so that one of the requests responds quickly?

Function not running with QtConcurrent::run() when using QFutureWatcher

I want to call a function to delete files and folders from the system in a parallel thread called by QtConcurrent::run() (Qt for Embedded Linux 4.8). Using only a QFuture<bool> with QFuture::waitForFinished() to grab the result (I need to run some code right after the operation), I was able to make the system work.
But I want to display the ongoing result of the operation in a QProgressBar derived class with its setValue(int) called via signals and slots mechanism from inside the delete function, and what I get with the above method is a freezed main thread while the operation isn't finished, and that is inadmissible.
So I though about using QFutureWatcher<bool> and connecting it's finished() signal to another slot containing the remaining code to be run after the delete operation is finished.
The problem I'm facing is that, when I do this, the delete function is simply not run by QtConcurrent::run()! I checked that with printed messages to Terminal. Everything that occurs is that the QFutureWatcher calls its finished() signal without any execution of the delete files function (and that also happens if I use QFutureWatcher::waitForFinished()).
Is this some bug from Qt?
Regarding code, it's pretty exactly as in Qt Assistant: create the QFuture and QFutureWatcher globally, connect the finished() signal with the slot, call QtConcurrent::run(), and setFuture() to the future. Nothing special.
Any help appreciated.
EDIT
Following the request of Kuba, here is the relevant part of the code:
//Declared globally in the .cpp
QFuture<bool> future;
QFutureWatcher<bool> watcher;
//
void SelectRecordToDeleteWidget::slotDeleteRecordStateMachine()
{
switch (deleteRecordStateMachine)
{
case PrepareToDelete:
{
//...
connect(&watcher,SIGNAL(finished()),this,SLOT(slotDeleteRecordStateMachine()),Qt::UniqueConnection);
//...
}
break;
case DeleteRecords:
{
//...
future = QtConcurrent::run(removeFiles, QString(DEFAULT_RECORD_DIR) + "/" + recordList.at(aaa).second.second, poProgressDialog, &itemCounter);
watcher.setFuture(future);
qApp->processEvents();
//...
}
break;
case FinishDelete:
{
//Run code after deleting files
}
break;
default:
break;
}
}
This is all the code using QFuture and QFutureWatcher. The removeFiles is as follows (not forgetting that it works well without QFutureWatcher):
bool removeFiles(const QString dirName, Interface::ProgressDialog* const poProgressDialog, qint32* const itemDeletedCounter)
{
bool result = true;
try
{
QDir dir(dirName);
if (dir.exists())
{
Q_FOREACH (QFileInfo info, dir.entryInfoList(QDir::NoDotAndDotDot | QDir::System | QDir::Hidden | QDir::AllDirs | QDir::Files, QDir::DirsFirst))
{
// if (Q_UNLIKELY(poProgressDialog->wasCanceled()))
// break;
if (info.isDir())
{
result = removeFiles(info.absoluteFilePath(),poProgressDialog,itemDeletedCounter);
if (!result)
return result;
}
else
{
result = QFile::remove(info.absoluteFilePath());
if (!result)
return result;
if (!QMetaObject::invokeMethod(poProgressDialog, "setValue",
Qt::BlockingQueuedConnection,
Q_ARG(qint32, *itemDeletedCounter)))
{
mDebugS(QString("removeFiles: %1QMetaObject::invokeMethod(poProgressDialog, \"setValue\"... failed!"));
}
++(*itemDeletedCounter);
// mDebugS(QString("removeFiles: %1").arg(*itemDeletedCounter));
}
}
result = dir.rmdir(dirName);
}
}
catch (...)
{
const QString strTemp = QString("An error in a call to removeFiles");
mDebugS(strTemp);
mLog(strTemp);
}
return result;
}

Function/Code Design with Concurrency in Swift

I'm trying to create my first app in Swift which involves making multiple requests to a website. These requests are each done using the block
var task = NSURLSession.sharedSession().dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in ... }
task.resume()
From what I understand this block uses a thread different to the main thread.
My question is, what is the best way to design code that relies on the values in that block? For instance, the ideal design (however not possible due to the fact that the thread executing these blocks is not the main thread) is
func prepareEmails() {
var names = getNames()
var emails = getEmails()
...
sendEmails()
}
func getNames() -> NSArray {
var names = nil
....
var task = NSURLSession.sharedSession().dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
names = ...
})
task.resume()
return names
}
func getEmails() -> NSArray {
var emails = nil
....
var task = NSURLSession.sharedSession().dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
emails = ...
})
task.resume()
return emails
}
However in the above design, most likely getNames() and getEmails() will return nil, as the the task will not have updated emails/name by the time it returns.
The alternative design (which I currently implement) is by effectively removing the 'prepareEmails' function and doing everything sequentially in the task functions
func prepareEmails() {
getNames()
}
func getNames() {
...
var task = NSURLSession.sharedSession().dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
getEmails(names)
})
task.resume()
}
func getEmails(names: NSArray) {
...
var task = NSURLSession.sharedSession().dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
sendEmails(emails, names)
})
task.resume()
}
Is there a more effective design than the latter? This is my first experience with concurrency, so any advice would be greatly appreciated.
The typical pattern when calling an asynchronous method that has a completionHandler parameter is to use the completionHandler closure pattern, yourself. So the methods don't return anything, but rather call a closure with the returned information as a parameter:
func getNames(completionHandler:(NSArray!)->()) {
....
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {data, response, error -> Void in
let names = ...
completionHandler(names)
}
task.resume()
}
func getEmails(completionHandler:(NSArray!)->()) {
....
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {data, response, error -> Void in
let emails = ...
completionHandler(emails)
}
task.resume()
}
Then, if you need to perform these sequentially, as suggested by your code sample (i.e. if the retrieval of emails was dependent upon the names returned by getNames), you could do something like:
func prepareEmails() {
getNames() { names in
getEmails() {emails in
sendEmails(names, emails) // I'm assuming the names and emails are in the input to this method
}
}
}
Or, if they can run concurrently, then you should do so, as it will be faster. The trick is how to make a third task dependent upon two other asynchronous tasks. The two traditional alternatives include
Wrapping each of these asynchronous tasks in its own asynchronous NSOperation, and then create a third task dependent upon those other two operations. This is probably beyond the scope of the question, but you can refer to the Operation Queue section of the Concurrency Programming Guide or see the Asynchronous vs Synchronous Operations and Subclassing Notes sections of the NSOperation Class Reference.
Use dispatch groups, entering the group before each request, leaving the group within the completion handler of each request, and then adding a dispatch group notification block (called when all of the group "enter" calls are matched by their corresponding "leave" calls):
func prepareEmails() {
let group = dispatch_group_create()
var emails: NSArray!
var names: NSArray!
dispatch_group_enter(group)
getNames() { results in
names = results
dispatch_group_leave(group)
}
dispatch_group_enter(group)
getEmails() {results in
emails = results
dispatch_group_leave(group)
}
dispatch_group_notify(group, dispatch_get_main_queue()) {
if names != nil && emails != nil {
self.sendEmails(names, emails)
} else {
// one or both of those requests failed; tell the user
}
}
}
Frankly, if there's any way to retrieve both the emails and names in a single network request, that's going to be far more efficient. But if you're stuck with two separate requests, you could do something like the above.
Note, I wouldn't generally use NSArray in my Swift code, but rather use an array of String objects (e.g. [String]). Furthermore, I'd put in error handling where I return the nature of the error if either of these fail. But hopefully this illustrates the concepts involved in (a) writing your own methods with completionHandler blocks; and (b) invoking a third bit of code dependent upon the completion of two other asynchronous tasks.
The answers above (particularly Rob's DispatchQueue based answer) describe the concurrency concepts necessary to run two tasks in parallel and then respond to the result. The answers lack error handling for clarity because traditionally, correct solutions to concurrency problems are quite verbose.
Not so with HoneyBee.
HoneyBee.start()
.setErrorHandler(handleErrorFunc)
.branch {
$0.chain(getNames)
+
$0.chain(getEmails)
}
.chain(sendEmails)
This code snippet manages all of the concurrency, routes all errors to handleErrorFunc and looks like the concurrent pattern that is desired.

can Multiple threads depend on a single manual Kill-event?

I have a MFC code with multiple threads that all make recursive calls to a subroutine, with different parameters.
In the beginning of the subroutine, I make a call to function CheckKillEvent():
bool CTestShellDlg::CheckKillEvent()
{
DWORD waitS;
waitS = WaitForSingleObject(h_KillEvent, 0);
switch (waitS)
{
case WAIT_OBJECT_0:
return true;
break;
case WAIT_TIMEOUT:
return false;
break;
default:
IERROR
break;
}
}
and return() immediately if CheckKillEvent returns true.
fyi, h_killEvent is initialized as:
h_KillEvent = CreateEvent(NULL, true, false, NULL);
ie, it has a manual reset.
However, these threads seem to take (literally) forever to finish after I set the Kill-event as below:
bool CTestShellDlg::KillThreads()
{
//Signall the killing event
SetEvent(h_KillEvent);
if (WaitForMultipleObjects(,,true,)==...)
{
ResetEvent(h_KillEvent);
return true; //Killing successful
}
else
return false; //Killing failed
}
The question is, is there an issue with calling CheckKillEvent() from multiple threads? Should the WaitForSingleObject() be done inside a critical section or something? Or is it simply my recursive code being bad at recursing back to a point where it no longer calls itself?
As Hans suggested in the comment, the problem was in fact with the message pump being blocked. Always best to assign separate threads for tasks that might take long or might themselves need access to the message pump.

Parallel.Invoke - Exception handling

My code runs 4 function to fill in information (Using Invoke) to a class such as:
class Person
{
int Age;
string name;
long ID;
bool isVegeterian
public static Person GetPerson(int LocalID)
{
Person person;
Parallel.Invoke(() => {GetAgeFromWebServiceX(person)},
() => {GetNameFromWebServiceY(person)},
() => {GetIDFromWebServiceZ(person)},
() =>
{
// connect to my database and get information if vegeterian (using LocalID)
....
if (!person.isVegetrian)
return null
....
});
}
}
My question is: I can not return null if he's not a vegeterian, but I want to able to stop all threads, stop processing and just return null. How can it be achieved?
To exit the Parallel.Invoke as early as possible you'd have to do three things:
Schedule the action that detects whether you want to exit early as the first action. It's then scheduled sooner (maybe as first, but that's not guaranteed) so you'll know sooner whether you want to exit.
Throw an exception when you detect the error and catch an AggregateException as Jon's answer indicates.
Use cancellation tokens. However, this only makes sense if you have an opportunity to check their IsCancellationRequested property.
Your code would then look as follows:
var cts = new CancellationTokenSource();
try
{
Parallel.Invoke(
new ParallelOptions { CancellationToken = cts.Token },
() =>
{
if (!person.IsVegetarian)
{
cts.Cancel();
throw new PersonIsNotVegetarianException();
}
},
() => { GetAgeFromWebServiceX(person, cts.Token) },
() => { GetNameFromWebServiceY(person, cts.Token) },
() => { GetIDFromWebServiceZ(person, cts.Token) }
);
}
catch (AggregateException e)
{
var cause = e.InnerExceptions[0];
// Check if cause is a PersonIsNotVegetarianException.
}
However, as I said, cancellation tokens only make sense if you can check them. So there should be an opportunity inside GetAgeFromWebServiceX to check the cancellation token and exit early, otherwise, passing tokens to these methods doesn't make sense.
Well, you can throw an exception from your action, catch AggregateException in GetPerson (i.e. put a try/catch block around Parallel.Invoke), check for it being the right kind of exception, and return null.
That fulfils everything except stopping all the threads. I think it's unlikely that you'll easily be able to stop already running tasks unless you start getting into cancellation tokens. You could stop further tasks from executing by keeping a boolean value to indicate whether any of the tasks so far has failed, and make each task check that before starting... it's somewhat ugly, but it will work.
I suspect that using "full" tasks instead of Parallel.Invoke would make all of this more elegant though.
Surely you need to load your Person from the database first anyway? As it is your code calls the Web services with a null.
If your logic really is sequential, do it sequentially and only do in parallel what makes sense.

Resources