Menu

#2 Ping waiting on WindowsNativeBridge when invoked concurrently

1.0
open
nobody
None
2016-09-14
2016-09-13
No

Hi,

I am having a problem where I concurrently do a ping for several addresses using an Executor, then my ping gets blocked while waiting for Windows Native Bridge. A part of the thread dump where one is holding the lock and another is blocked. Also attached the code.

Is icmp4j thread safe? What would be a solution to this?


"Pool-4-SubtaskRunner-1" #316 prio=5 os_prio=0 tid=0x000000001d7f5000 nid=0x21d8 waiting for monitor entry [0x000000003931d000]

java.lang.Thread.State: BLOCKED (on object monitor)
at org.icmp4j.platform.windows.WindowsNativeBridge.executePingRequest(WindowsNativeBridge.java:107)
- waiting to lock <0x00000007aea22480> (a org.icmp4j.platform.windows.WindowsNativeBridge)
at org.icmp4j.IcmpPingUtil.executePingRequest(IcmpPingUtil.java:117)
at com.nms.net.ping.Ping.ping(Ping.java:59)
...
at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:368)
at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:215)
at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:144)
at org.springframework.batch.core.step.tasklet.TaskletStep.doExecute(TaskletStep.java:257)
at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:198)
at org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:148)
at org.springframework.batch.core.job.flow.JobFlowExecutor.executeStep(JobFlowExecutor.java:64)
at org.springframework.batch.core.job.flow.support.state.StepState.handle(StepState.java:67)
at org.springframework.batch.core.job.flow.support.SimpleFlow.resume(SimpleFlow.java:165)
at org.springframework.batch.core.job.flow.support.SimpleFlow.start(SimpleFlow.java:144)
at org.springframework.batch.core.job.flow.support.state.SplitState$1.call(SplitState.java:93)
at org.springframework.batch.core.job.flow.support.state.SplitState$1.call(SplitState.java:90)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at com.nms.jobs.service.internal.spring.JobExecutionRegister.run(JobExecutionRegister.java:52)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)


"Pool-2-SubtaskRunner-1" #114 prio=5 os_prio=0 tid=0x000000002810b000 nid=0x804 in Object.wait() [0x000000003598c000]

java.lang.Thread.State: RUNNABLE

at com.sun.jna.Native.initIDs(Native Method)
at com.sun.jna.Native.<clinit>(Native.java:135)
at org.icmp4j.util.JnaUtil.loadLibraryNoException(JnaUtil.java:152)
at org.icmp4j.util.JnaUtil.loadLibrary(JnaUtil.java:86)
- locked <0x00000007aea243f8> (a java.lang.Class for org.icmp4j.util.JnaUtil)
at org.icmp4j.platform.windows.jna.LibraryUtil.initialize(LibraryUtil.java:58)
at org.icmp4j.platform.windows.WindowsNativeBridge.initialize(WindowsNativeBridge.java:62)
at org.icmp4j.Icmp4jUtil.initialize(Icmp4jUtil.java:101)
- locked <0x00000007aea24468> (a java.lang.Class for org.icmp4j.Icmp4jUtil)
at org.icmp4j.IcmpPingUtil.executePingRequest(IcmpPingUtil.java:97)
at com.nms.net.ping.Ping.ping(Ping.java:59)
...
at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:368)
at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:215)
at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:144)
at org.springframework.batch.core.step.tasklet.TaskletStep.doExecute(TaskletStep.java:257)
at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:198)
at org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:148)
at org.springframework.batch.core.job.flow.JobFlowExecutor.executeStep(JobFlowExecutor.java:64)
at org.springframework.batch.core.job.flow.support.state.StepState.handle(StepState.java:67)
at org.springframework.batch.core.job.flow.support.SimpleFlow.resume(SimpleFlow.java:165)
at org.springframework.batch.core.job.flow.support.SimpleFlow.start(SimpleFlow.java:144)
at org.springframework.batch.core.job.flow.support.state.SplitState$1.call(SplitState.java:93)
at org.springframework.batch.core.job.flow.support.state.SplitState$1.call(SplitState.java:90)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at com.nms.jobs.service.internal.spring.JobExecutionRegister.run(JobExecutionRegister.java:52)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)

Code:
public Boolean ping(final String ipAddress, final int timeout) throws IOException {
final IcmpPingRequest request = IcmpPingUtil.createIcmpPingRequest();
request.setHost(ipAddress);
request.setTimeout(timeout);

    final IcmpPingResponse response = IcmpPingUtil.executePingRequest(request);

    return response.getSuccessFlag();
}

I see that in your example, you have included a rest period (Thread.sleep(1000)). Is this required?

Thanks.

Discussion

  • Sal Ingrilli

    Sal Ingrilli - 2016-09-13

    The WindowsNativeBridge is synchronized, so no matter how many threads you have running, only 1 ping will execute at a time.

    The reason we did this is that it appears that the Win32 native APIs are not thread safe, or rather, they probably hold state as static variables, and so when multiple threads call IcmpSendEcho (), the results are corrupted.

    Your options are:
    1. Use shortpasta-icmp (https://sourceforge.net/projects/shortpasta-icmp/?source=directory) which uses raw sockets instead of IcmpSendEcho, but most likely requires you to run Java as administrator
    2. Develop a Windows ProcessNativeBridge that spaws the native ping.exe
    3. Develop a thread-safe version of WindowsNativeBridge

    If your you / your company wants to support the development, we can help with #2 and #3.

     
  • laurent buhler

    laurent buhler - 2016-09-13

    icmp4j is thread safe on all platforms,
    On unix platforms, you can have concurrent threads calling icmp4j

     

    Last edit: laurent buhler 2016-09-13
  • Sal Ingrilli

    Sal Ingrilli - 2016-09-13

    Yes, and to make sure everybody understands, icmp4j is thread safe on ALL platforms.
    That's why the Windows implementation is synchronized - so that it becomes thread safe.

     
  • Anusha Damodaran

    In the above example though, threads are forever waiting for the WindowsNativeBridge. There is some sort of timing issue where all threads are blocked and the holding thread does not release the lock for the WindowsNativeBridge.This does not happen consistently.

    So, you mean that you made icmp4j thread safe, but since Win32 native APIs are not thread safe, we might encounter this problem when we use icmp4j?

     
  • Sal Ingrilli

    Sal Ingrilli - 2016-09-13

    Your threads are blocked, not deadlocked. Blocked means that they will wait to enter the synchronized block until another thread exits that block. It's easy to find if the threads are deadlocked: issue a thread dump, and at the bottom it tells you that there are deadlocks. If there is a deadlock in icmp4j, send over the full thread dump and we will take a look at it immediately.

    As for your threads blocking for ever, a reason for which your threads may be blocking for ever, is if the request timeout is set to 0. Make sure to call IcmpPingRequest.setTimeout () with something reasonable, like 10,000. Otherwise 0 means infinite, and a ping may sit there waiting for a response that never comes back, and no other pings will work.

    As for the thread-safety comment, I am saying the opposite of what you are saying. icmp4j is thread-safe, and you can call it from many threads without corrupting the work of any individual thread. This is what makes it thread-safe. icmp4j protects you from dealing with thread-safety.

    Finally, if our current implementation of icmp4j has any bug, we'll fix it. And if you want to sponsor the development of parallel pings for Windows, we can work on a native ping.exe implementation and a native jna/jni implementation. But we have done that before, and it is much more work than we want to do for free...

     
  • Sal Ingrilli

    Sal Ingrilli - 2016-09-14

    Anusha, it seems that you are a student at a univerisity.
    If you can confirm that, please email me directly at shortpasta [at] gmail.com and I will implement a WindowsProcessNativeBridge for you.

     

Log in to post a comment.