Provide example and better document disallowBlockingCallsInside
simonbasle opened this issue · 0 comments
simonbasle commented
After some trial-and-error, here is an example that demonstrates the feature:
public class BlockingDisallowTest {
static {
BlockHound.install(b -> b
.allowBlockingCallsInside(NonBlockingClass.class.getName(), "outer")
.disallowBlockingCallsInside(NonBlockingClass.class.getName(), "inner")
);
}
@Test
public void shouldDisallow() throws InterruptedException {
NonBlockingClass nbc = new NonBlockingClass();
AtomicReference<BlockingOperationError> boeRef = new AtomicReference<>();
//to trip BlockHound in the first place, we must be in a nonblocking thread
CountDownLatch latch = new CountDownLatch(1);
Schedulers.parallel().schedule(() -> {
try {
nbc.outer();
}
catch (BlockingOperationError boe) {
boeRef.set(boe);
}
finally {
latch.countDown();
}
});
latch.await(5, TimeUnit.SECONDS);
//given the configuration we expect that yield is allowed, but the sleep inside example2 isn't
assertThat(boeRef.get())
.isNotNull()
.hasMessage("Blocking call! java.lang.Thread.sleep")
.hasStackTraceContaining("at com.example.BlockingDisallowTest$NonBlockingClass.inner")
.hasStackTraceContaining("at com.example.BlockingDisallowTest$NonBlockingClass.outer");
}
static class NonBlockingClass {
String inner() {
try {
//if this trips BlockHound, the test fails (inner not in the stacktrace)
Thread.sleep(50);
}
catch (InterruptedException e) {
e.printStackTrace();
}
return "example";
}
String outer() {
try {
Thread.sleep(50);
}
catch (InterruptedException e) {
e.printStackTrace();
}
Thread.yield();
return inner();
}
}
}
It should be noted that disallow seems to only make sense as an inner
exception to an outer
allow case:
- the reverse can simply be achieved by NOT allowing blocking calls inside
outer
in the first place, and merely allowinginner
- it doesn't mark the method as a non-blocking execution context. the method MUST still be called from a thread that is already detected as non-blocking by BlockHound (eg. via the
threadPredicate
) for the allow/disallow evaluation to take place