Deadlock instead of an exception when calling get() from the inside FutureTask.run() - java.util.concurrent

Recently, due to an error in my code, I created a recursive call (infinite loop, in fact). One of the methods involved in the loop used a pre-computed task. It can be summarized as:
ConcurrentHashMap<String, FutureTask<Integer>> cache = new ConcurrentHashMap<>();
int method1() {
var task = cache.computeIfAbsent("key", k -> new FutureTask<>(this::method2));
task.run();
try {
return task.get();
} catch (InterruptedException | ExecutionException e) {
throw new RuntimeException(e);
}
}
int method2() {
if (1 + 1 != 4) { // this wasn't so obvious of course...
return method1();
}
return 1;
}
In short: FutureTask's get() was called while inside its run() execution.
To my surprise, it resulted in a deadlock, as get() makes no checks and parks the current thread unconditionally.
I know I shot myself in the foot with low-level primitives, but is there a reason or use case why get() doesn't make a check and
throw an exception when called from the same thread as the runner thread of the task?

Related

Waiting for an external event before continue in unit test

Context:
I'm writing unit test for a gRPC service. I want to verify that the method of the mock on the server side is called. I'm using easy mock. To be sure we get the response of gRPC (whatever it is) I need to suspend the thread before easy mock verify the calls.
So I tried something like this using LockSupport:
#Test
public void alphaMethodTest() throws Exception
{
Dummy dummy = createNiceMock(Dummy.class);
dummy.alphaMethod(anyBoolean());
expectLastCall().once();
EasyMock.replay(dummy);
DummyServiceGrpcImpl dummyServiceGrpc = new DummyServiceGrpcImpl();
bcreuServiceGrpc.setDummy(dummy);
DummyServiceGrpc.DummyServiceStub stub = setupDummyServiceStub();
Thread thread = Thread.currentThread();
stub.alphaMethod(emptyRequest, new StreamObserver<X>(){
#Override
public void onNext(X value) {
LockSupport.unpark(thread);
}
}
Instant expirationTime = Instant.now().plus(pDuration);
LockSupport.parkUntil(expirationTime.toEpochMilli());
verify(dummy);
}
But I have many tests like this one (around 40) and I suspect threading issue. I usually get one or two failing the verify step, sometime all of them pass. I try to use a ReentrantLock with Condition instead. But again some are failing (IllegalMonitorStateException on the signalAll):
#Test
public void alphaMethodTest() throws Exception
{
Dummy dummy = createNiceMock(Dummy.class);
dummy.alphaMethod(anyBoolean());
expectLastCall().once();
EasyMock.replay(dummy);
DummyServiceGrpcImpl dummyServiceGrpc = new DummyServiceGrpcImpl();
bcreuServiceGrpc.setDummy(dummy);
DummyServiceGrpc.DummyServiceStub stub = setupDummyServiceStub();
ReentrantLock lock = new ReentrantLock();
Condition conditionPromiseTerminated = lock.newCondition();
stub.alphaMethod(emptyRequest, new StreamObserver<X>(){
#Override
public void onNext(X value) {
conditionPromiseTerminated.signalAll();
}
}
Instant expirationTime = Instant.now().plus(pDuration);
conditionPromiseTerminated.awaitUntil(new Date(expirationTime.toEpochMilli()));
verify(dummy);
}
I'm sorry not providing runnable example for you, my current code is using a private API :/.
Do you think LockSupport may cause trouble because of the multiple tests running? Am I missing something using lock support or reentrant lock. Do you think of any other class of the concurrent API that would suit better my needs?
LockSupport is a bit dangerous, you will need to read the documentation closely and find out that:
The call spuriously (that is, for no reason) returns.
So when you think your code will do some "waiting", it might simply return immediately. The simplest reason for that would be this for example, but there could be other reasons too.
When using ReentrantLock, all of them should fail with IllegalMonitorStateException, because you never acquire the lock via ReentrantLock::lock. And stop using new Date(...), it is deprecated for a reason.
I think you are over-complicating things, you could do the same signaling with a plain lock, a simplified example:
public static void main(String[] args) {
Object lock = new Object();
Thread first = new Thread(() -> {
synchronized (lock) {
System.out.println("Locked");
try {
System.out.println("Sleeping");
lock.wait();
System.out.println("Waked up");
} catch (InterruptedException e) {
// these are your tests, no one should interrupt
// unless it's yourself
throw new RuntimeException(e);
}
}
});
first.start();
sleepOneSecond();
Thread second = new Thread(() -> {
synchronized (lock) {
System.out.println("notifying waiting threads");
lock.notify();
}
});
second.start();
}
private static void sleepOneSecond() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Notice the output:
Locked
Sleeping
notifying waiting threads
Waked up
It should be obvious how the "communication" (signaling) between threads happens.

Is this code exceptions handled correctly?

In the following code, it is possible that event throws exception and it may be not handled in even handler, (rare but its still the case)
I want keep "lck2" unlocked while executing the event, because I don't want main thread block for "mtx2", reason is nothing more than optimization.
Can I guarantee that "lck2" is always released in catch block? or there could be runtime exceptions and therefore it may cause deadlocks or some unexpected behavior?
std::unique_lock<std::mutex>lck2(mtx2); // lock used for waiting for event.
while (_isRunning)
{
try
{
while (_isRunning)
{
// cvar2 is condition variable
cvar2.wait(lck2, [&] {return invoke; }); // wait until invoke == true
if (invoke) // if event must be invoked
{
lck2.unlock();
OnEvent(this, someproperty); // may throw exception
lck2.lock();
invoke = false; // execution completed
}
}
}
catch (...) // we need to keep this thread alive at all costs!
{
lck2.lock(); // is this safe?
invoke = false;
}
}
A rewrite of your code would probably be more appropriate, to make it easier for another developer to work on the code. I will show you two rewrites:
First, (Bad)
while (true)
{
try
{
{
std::lock_guard<std::mutex> lckx(mtx2);
if(!_isRunning)
break; //out of the main loop
}
bool should_invoke = false;
{
std::unique_lock<std::mutex> lck2(mtx2);
cvar2.wait(lck2, [&] {return invoke; });
should_invoke = invoke;
}
if (should_invoke) // if event must be invoked
{
OnEvent(this, someproperty); // may throw exception
{
std::lock_guard<std:mutex> lckx(mtx2);
invoke = false; // execution completed
}
}
}
catch (...) // we need to keep this thread alive at all costs!
{
std::lock_guard<std:mutex> lckx(mtx2);
invoke = false;
}
}
Second, (Good)
Breaking the (first) code into smaller functional units; we also note that the expression cvar2.wait(lck2, [&]{ return invoke; }) will suspend execution and only return if woken up and invoke is true, then we can infer that we only need that expression to wait. Hence we can discard the superfluous use of invoke. Hence we have:
void do_work(){
while(is_running()){
try{
wait_for_invocation();
OnEvent(this, someproperty); // may throw exception
set_invocation_state(false);
catch(...){
set_invocation_state(false);
}
}
}
Where the helpers are defined:
bool is_running(){
std::lock_guard<std::mutex> lckx(mtx2);
return _isRunning;
}
void wait_for_invocation(){
std::unique_lock<std::mutex> lck2(mtx2);
cvar2.wait(lck2, [&] {return invoke; });
}
void set_invocation_state(bool state){
std::lock_guard<std::mutex> lckx(mtx2);
invoke = state;
}

How to return value from nested task in c++/cx?

I have a bunch of threaded tasks like this after each other:
create_task(somewinrtasyncfunction()).then([this(variable_that_the_last_task_returned)
{
//task here
return info;
}).then([this](info)
{
//another task here
return status});
Now I want to use status outside the tasks, in the function that called it. How would I access it?
You return the task (or value) created by create_task(...).then(...).then(...).
If you need to get the result synchronously, you can try calling .get() on the task but that will not work on the main UI thread(s) of your application, and is not something you should do. The code might work on a background thread today, but you might end up calling the function on the UI thread in the future -- perhaps by some very round-about fashion -- and then your app will crash. The only way to fix the app will be to re-engineer your code to be asynchronous... like it should have been in the first place.
Also, note that trying to do your own work-arounds to get the value synchronously (like calling WaitForSingleObjectEx() on an object signaled in the task) can deadlock the UI thread for many WinRT Async methods. Don't do it!
You should continue the asynchronous chain to act on the value. Here is a simple example; call test() from your main UI thread.
concurrency::task<int> get_double_async(int value)
{
return concurrency::create_task(
[value]()
{
return value * 2;
});
}
// DON'T DO THIS - IT IS A BUG FARM WAITING TO HAPPEN!
int try_calling_get()
{
auto value = 2;
value = get_double_async(value).get(); // TODO: Don't do this!
value = get_double_async(value).get(); // TODO: Don't do this!
return value;
}
concurrency::task<int> do_it_properly()
{
auto value = 2;
return get_double_async(value).then([](int value)
{
return get_double_async(value).then([](int value)
{
return value;
});
});
}
void test()
{
wchar_t buff[255];
swprintf_s(buff, L"test() being called on thread %d.\r\n", GetCurrentThreadId());
OutputDebugString(buff);
// this will fail at runtime if called from UI thread
try
{
auto x = try_calling_get();
}
catch (const concurrency::invalid_operation& op)
{
// "Illegal to wait on a task in a Windows Runtime STA"
swprintf_s(buff, L"try_calling_get() threw '%hs'; thread is %d.\r\n",
op.what(), GetCurrentThreadId());
OutputDebugString(buff);
}
// this will "work", but only because it is forced into a threadpool thread
concurrency::create_task([]
{
auto x = try_calling_get(); // TODO: Don't do this!
wchar_t buff[255];
swprintf_s(buff, L"try_calling_get() returned %d; thread is %d.\r\n",
x, GetCurrentThreadId());
OutputDebugString(buff);
});
// this is the preferred way to do it
do_it_properly().then([](int x)
{
wchar_t buff[255];
swprintf_s(buff, L"do_it_properly() returned %d; thread is %d.\r\n",
x, GetCurrentThreadId());
OutputDebugString(buff);
});
}
Note that this example uses value-based continuations .then([](int value){...}) rather than task-based continuations .then([](task<int> value){...}); you would use task-based continuations if you wanted control over things like exceptions.
Here's a sample run (the thread IDs will be different every time, and sometimes the last two will be the same)
test() being called on thread 3576.
First-chance exception at 0x77134598 in UniversalNativeApp.Windows.exe: Microsoft C++ exception: Concurrency::invalid_operation at memory location 0x038CEC94.
try_calling_get() threw 'Illegal to wait on a task in a Windows Runtime STA'; thread is 3576.
try_calling_get() returned 8; thread is 5972.
do_it_properly() returned 8; thread is 9976.

Calling `f()` once regardless of exceptions

My understanding may be incorrect but, reading the documentation for call_once, it appears that if multiple threads are calling it simultaneously with the same once_flag and the first thread throws an exception, one of the other threads will have its callable called (and so forth until one callable returns without throwing).
My question is, if I have multiple thread all the with the same callable and I want the callable to be called truly once regardless of an exception and I want to know about the exception, do I have no choice but to do this:
void call_really_just_once()
{
std::exception_ptr e;
std::call_once(some_once_flag_, [&]
{
try
{
may_throw();
}
catch(...)
{
e = std::current_exception();
}
});
if(e)
{
std::rethrow_exception(e);
}
}

Notifying user of Access Violation like Exceptions

I have a multi-threaded application for retrieving database information and storing data as linked list of objects which i use further to do some operations on them and output the results. During the course of execution, I am bound to encounter exceptions like Access Violation due to the nature of pointers.
I certainly know these exceptions (Hardware or Software) are not caught by regular try catch in C++ and also know that we have avoid such exceptions by reprogramming culprit section.. But because i dont have control of data in database, sometimes I end up getting the exception and whole program crashes.
I would like to know if there a way to notify the user of Access Violation and preventing the affected thread from crashing other threads or whole process.
int ex;
pthread_mutex_t lk;
void sighandler(int a){
pthread_mutex_unlock(&lk);
}
static void *func1(void * arg) {
while(1) {
pthread_mutex_lock(&lk);
if(ex<=0) {
try {
char *p=0;*p = 0;
} catch(...) {
printf("eerr");
}
pthread_mutex_unlock(&lk);
break;
}
ex--;
pthread_mutex_unlock(&lk);
}
return 0;
}
static void *func2(void * arg) {
while(1) {
pthread_mutex_lock(&lk);
if(ex<=-100) {
pthread_mutex_unlock(&lk);
break;
}
ex-=2;
pthread_mutex_unlock(&lk);
}
return 0;
}
int main(void)
{
signal(SIGSEGV,sighandler);
ex=100;
pthread_t pth[2];
pthread_mutex_init(&lk,NULL);
pthread_create(&pth[0],NULL,func1,NULL);
pthread_create(&pth[1],NULL,func2,NULL);
pthread_join(pth[0],NULL);
pthread_join(pth[1],NULL);
return 0;
}
I tried to create simpler version of what i would like to know.. There would definitely be access violation in func1 (*p=0) but I would like the func2 to run unhindered while notifying the user of access violation through some kind of log or through controller thread.
Thank You