pSpaces / jSpace

Programming with Spaces in Java
MIT License
17 stars 12 forks source link

RemoteSpace in conn mode won't throw InterruptedException on blocking calls such as query, get etc. #14

Closed TheAIBot closed 6 years ago

TheAIBot commented 6 years ago

When you connect with a RemoteSpace using keep, it's possible to return from blocking calls like query and get by interrupting the thread. A RemoteSpace using conn won't return from blocking calls when calling interrupt on the thread. Obviously it's really useful to cancel blocking calls so preferably conn mode should also throw InterruptedException in blocking calls. Even the API for RemoteSpace.query says that it should throw InterruptedException.

Object[] org.jspace.RemoteSpace.query(TemplateField... fields) throws InterruptedException

I made a minimal example to show the issue. It creates both both a RemoteSpace in conn and keep mode. Then it interrupts the thread t1 while the the thread is executing remoteConn.query. You would expect it to throw here but it doesn't. Then the item the query is looking for is inserted and the query returns. Now the execution has arrived at remoteKeep.get which throws an InterruptedException.

import java.io.IOException;
import java.net.UnknownHostException;

import org.jspace.ActualField;
import org.jspace.RemoteSpace;
import org.jspace.SequentialSpace;
import org.jspace.SpaceRepository;

public class TestStarter {
    static boolean isThreadStarted = false;

    public static void main(String[] args) throws UnknownHostException, IOException {
        final SpaceRepository repConn = new SpaceRepository();
        repConn.addGate("tcp://localhost:1289/?conn");
        final SequentialSpace spaceConn = new SequentialSpace();
        repConn.add("spaceConn", spaceConn);
        final RemoteSpace remoteConn = new RemoteSpace("tcp://localhost:1289/spaceConn?conn");

        final SpaceRepository repKeep = new SpaceRepository();
        repKeep.addGate("tcp://localhost:1290/?keep");
        final SequentialSpace spaceKeep = new SequentialSpace();
        repKeep.add("spaceKeep", spaceKeep);
        final RemoteSpace remoteKeep = new RemoteSpace("tcp://localhost:1290/spaceKeep?keep");

        final Thread t1 = new Thread(() -> {
            try {
                isThreadStarted = true;
                remoteConn.query(new ActualField("something"));
            } catch (InterruptedException e) {
                System.out.println("Would expect query to throw InterruptException");
                e.printStackTrace(System.out);
            }

            try {
                remoteKeep.get(new ActualField("something else"));
            } catch (InterruptedException e) {
                System.out.println("But actually the next call(here it's get) throws the exception");
                e.printStackTrace(System.out);
            }
        });
        t1.start();
        //first wait for the thread to start
        while (!isThreadStarted) {
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {}
        }
        //then interrupt the thread while it's running the query
        t1.interrupt();

        //after interrupting we would expect the query to throw an error and stop
        //so remoteKeep.get shouldn't run.
        try {
            spaceConn.put("something");
        } catch (InterruptedException e) {}
    }
}
michele-loreti commented 6 years ago

This aspect has been fixed. However it is important to remark that the use of "t.interrupt()" is inappropriate. Indeed, it may lead to inconsistent configurations.