Quantcast
Channel: zeroturnaround.com » All Posts
Viewing all articles
Browse latest Browse all 2540

Potential Deadlocks In all WildFly 10 (+?) installations

$
0
0

When a jrebel agent (v 6.2.5 or later) is attached to the JVM it alters the WildFly EJB interceptors that exists between the EJB pojos and the EJB reference types (call site code). More specifically it:

  • Introduces this new method: org.jboss.as.ee.component.ViewService$View.__invoke()
  • Modifies existing method: org.jboss.as.ee.component.ViewService$View.invoke() (By introducing the synchronized modifier)

When jrebel has done this to EJB @Singleton components in WildFly …and when their methods are invoked concurrently we can end up in a deadlocked situation.

Try it !
The arquillian test below can cause such deadlocks. To make it deadlock, all you have to do is to add the -javaagent:/path/to/jrebel.jar argument in standalone.conf (or in Eclipse: in the program launcher). The example will only deadlock when the jrebel agent is associated with the jvm.


@SuppressWarnings("nls")
@RunWith(Arquillian.class)
public class DeadLockArquillianTest {

    @Deployment
    public static WebArchive createDeployment() {
        return ShrinkWrap.create(WebArchive.class) //
                .addClass(FriendOne.class)//
                .addClass(FriendTwo.class);
    }

    @EJB
    FriendOne one;

    @EJB
    FriendTwo two;

    @Test
    public void goNutz() throws Exception {

        // run with
        // -javaagent:/path/to/jrebel/jrebel.jar
        // to deadlock the threads....

        int nThreads = 2;

        ExecutorService e = Executors.newFixedThreadPool(nThreads);

        for (int i = 0; i < nThreads; i++) {
            final String label = String.format("Thread %02d", i);
            e.submit(new Runnable() {
                @Override
                public void run() {
                    for (int j = 0; j < 100; j++) {
                        if (j % 2 == 0) {
                            one.sayHello();
                        } else {
                            two.sayHello();
                        }
                        System.out.format("%s methodcall %3d ...%n", label, j);
                    }
                }
            });
        }

        System.out.println("WAITING");
        e.shutdown();
        e.awaitTermination(2, TimeUnit.MINUTES);
    }

@Startup
@Singleton
@Lock(LockType.READ)
public class FriendOne {

    @EJB
    FriendTwo otherFriend;

    @Lock(LockType.READ)
    public String sayHello() {
        return "hello" + otherFriend.format("1hello world");
    }

    @Lock(LockType.READ)
    public String format(String input) {
        return "FORMATTED by FriendOne TO: " + input;
    }
}

@Startup
@Singleton
@Lock(LockType.READ)
public class FriendTwo {
    
    @EJB
    FriendOne otherFriend;

    @Lock(LockType.READ)
    public String sayHello() {
        return "hello" + otherFriend.format("2hello world");
    }

    @Lock(LockType.READ)
    public String format(String input) {
        return "FORMATTED by FriendTwo TO: " + input;
    }

}

Note that the READ locks effectively means that multiple threads may be in the EJB instances at the same time. That is also why the system doesn’t deadlock in the absence of the jrebel agent.

  • This topic was modified 21 hours, 55 minutes ago by  Nicky Mølholm. Reason: formulation

Viewing all articles
Browse latest Browse all 2540

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>