Enhance TimeoutException to include more details

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

Enhance TimeoutException to include more details

Jason Mehrens
Hello Concurrency-interest,

A lot of the synchronizers included in jsr166 that throw TimeoutException do not include the information that is useful to know when such an event occurs. I'm assuming that performance, keeping the code simple, and not crippling evolution of the code are the main drivers for the way it is today.

With those goals in mind, could TimeoutException be modified to include:
1. Information about the timeout value with a time unit mapped to getMessage().
2. A cause Throwable that contained the current stacktrace of the 'owner' thread (ASQ.getExclusiveOwnerThread().getStackTrace()).
3. Suppressed exceptions that contained all of the threads waiting to acquire (ASQ.getQueuedThreads())


For example, if take a FutureTask with 4 threads:
1. A thread calls FutureTask.run
2. Two threads call FutureTask.get.
3. One thread calls FutureTask.get(1, SECONDS) and logs the timeout.


To convert the stacktraces to a Throwable I abused the IllegalStateException for a proof of concept (no security manager).
The timeout could be described using the following (hopefully the formatting works).

=================================================================================
java.util.concurrent.TimeoutException: 1 SECONDS
    at java.util.concurrent.FutureTask.get(FutureTask.java:205)
    at TimeoutExampleOutput.testFutureTask(TimeoutExampleOutput.java:46)
    at TimeoutExampleOutput.main(TimeoutExampleOutput.java:12)
    Suppressed: java.lang.IllegalStateException: [14-WAITING-Thread[pool-1-thread-2,5,main]]
        at sun.misc.Unsafe.park(Native Method)
        at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
        at java.util.concurrent.FutureTask.awaitDone(FutureTask.java:429)
        at java.util.concurrent.FutureTask.get(FutureTask.java:191)
        at TimeoutExampleOutput$2.run(TimeoutExampleOutput.java:37)
        at java.lang.Thread.run(Thread.java:745)
    Suppressed: java.lang.IllegalStateException: [15-WAITING-Thread[pool-1-thread-3,5,main]]
        at sun.misc.Unsafe.park(Native Method)
        at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
        at java.util.concurrent.FutureTask.awaitDone(FutureTask.java:429)
        at java.util.concurrent.FutureTask.get(FutureTask.java:191)
        at TimeoutExampleOutput$2.run(TimeoutExampleOutput.java:37)
        at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.IllegalStateException: [13-TIMED_WAITING-Thread[pool-1-thread-1,5,main]]
    at java.lang.Thread.sleep(Native Method)
    at TimeoutExampleOutput$1.call(TimeoutExampleOutput.java:19)
    at TimeoutExampleOutput$1.call(TimeoutExampleOutput.java:16)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.lang.Thread.run(Thread.java:745)
==================================================================================

The state of all 4 threads is described in this one failure.  You can see that this thread timed out was caused by the worker taking a nap and everyone else is being held up because of it.

I would assume there is a way to capture some of this state in TimeoutException and then delay the evaluation of that state until some TimeoutException method is called like getCause or getMessage and retain most of the performance goals.  Or perhaps adding a method to TimeoutException to opt into this information.

Any thoughts on this?

Regards,

Jason

_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|

Re: Enhance TimeoutException to include more details

David Holmes-6
Hi Jason,

What you propose is a diagnostic capability which is way beyond what a
simple exception should be involved in. It simply isn't the role of
TimeoutException to try and expose all that.

How hard is it to gather that information when you detect the
TimeoutException? There are a couple of API's that could be used.

Cheers,
David

> -----Original Message-----
> From: [hidden email] [mailto:concurrency-
> [hidden email]] On Behalf Of Jason Mehrens
> Sent: Friday, December 11, 2015 4:27 AM
> To: concurrency-interest
> Subject: [concurrency-interest] Enhance TimeoutException to include
> more details
>
> Hello Concurrency-interest,
>
> A lot of the synchronizers included in jsr166 that throw
> TimeoutException do not include the information that is useful to know
> when such an event occurs. I'm assuming that performance, keeping the
> code simple, and not crippling evolution of the code are the main
> drivers for the way it is today.
>
> With those goals in mind, could TimeoutException be modified to
> include:
> 1. Information about the timeout value with a time unit mapped to
> getMessage().
> 2. A cause Throwable that contained the current stacktrace of the
> 'owner' thread (ASQ.getExclusiveOwnerThread().getStackTrace()).
> 3. Suppressed exceptions that contained all of the threads waiting to
> acquire (ASQ.getQueuedThreads())
>
>
> For example, if take a FutureTask with 4 threads:
> 1. A thread calls FutureTask.run
> 2. Two threads call FutureTask.get.
> 3. One thread calls FutureTask.get(1, SECONDS) and logs the timeout.
>
>
> To convert the stacktraces to a Throwable I abused the
> IllegalStateException for a proof of concept (no security manager).
> The timeout could be described using the following (hopefully the
> formatting works).
>
> =======================================================================
> ==========
> java.util.concurrent.TimeoutException: 1 SECONDS
>     at java.util.concurrent.FutureTask.get(FutureTask.java:205)
>     at
> TimeoutExampleOutput.testFutureTask(TimeoutExampleOutput.java:46)
>     at TimeoutExampleOutput.main(TimeoutExampleOutput.java:12)
>     Suppressed: java.lang.IllegalStateException: [14-WAITING-
> Thread[pool-1-thread-2,5,main]]
>         at sun.misc.Unsafe.park(Native Method)
>         at
> java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
>         at
> java.util.concurrent.FutureTask.awaitDone(FutureTask.java:429)
>         at java.util.concurrent.FutureTask.get(FutureTask.java:191)
>         at TimeoutExampleOutput$2.run(TimeoutExampleOutput.java:37)
>         at java.lang.Thread.run(Thread.java:745)
>     Suppressed: java.lang.IllegalStateException: [15-WAITING-
> Thread[pool-1-thread-3,5,main]]
>         at sun.misc.Unsafe.park(Native Method)
>         at
> java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
>         at
> java.util.concurrent.FutureTask.awaitDone(FutureTask.java:429)
>         at java.util.concurrent.FutureTask.get(FutureTask.java:191)
>         at TimeoutExampleOutput$2.run(TimeoutExampleOutput.java:37)
>         at java.lang.Thread.run(Thread.java:745)
> Caused by: java.lang.IllegalStateException: [13-TIMED_WAITING-
> Thread[pool-1-thread-1,5,main]]
>     at java.lang.Thread.sleep(Native Method)
>     at TimeoutExampleOutput$1.call(TimeoutExampleOutput.java:19)
>     at TimeoutExampleOutput$1.call(TimeoutExampleOutput.java:16)
>     at java.util.concurrent.FutureTask.run(FutureTask.java:266)
>     at java.lang.Thread.run(Thread.java:745)
> =======================================================================
> ===========
>
> The state of all 4 threads is described in this one failure.  You can
> see that this thread timed out was caused by the worker taking a nap
> and everyone else is being held up because of it.
>
> I would assume there is a way to capture some of this state in
> TimeoutException and then delay the evaluation of that state until some
> TimeoutException method is called like getCause or getMessage and
> retain most of the performance goals.  Or perhaps adding a method to
> TimeoutException to opt into this information.
>
> Any thoughts on this?
>
> Regards,
>
> Jason
>
> _______________________________________________
> Concurrency-interest mailing list
> [hidden email]
> http://cs.oswego.edu/mailman/listinfo/concurrency-interest


_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|

Re: Enhance TimeoutException to include more details

Jason Mehrens
Yes the role of TimeoutException is what I'm asking so you have answered my question.  The interesting part is that receiver of a timeout exception is usually a victim which means the information contained in the timeout exception is almost useless.  You have to admit that we set the bar pretty low when we don't even give back the value of the timeout.  I suppose that could lead to users coding parsers for that information.

Using the example of FutureTask there are no (nor should there be) accessors to get the id or the actual runner of the FutureTask.  So gathering all the information for a JVM is not too hard.  Gathering the exact information for this specific synchronizer very difficult.  Because of where TimeoutException is constructed it would have safe access to all the context required including the assailant thread.  Even if TimeoutException had a methods that returned getExclusiveOwnerThread().getId() and ids of the getQueuedThreads would at add some utility without adding diagnostics directly.

Jason




________________________________________
From: David Holmes <[hidden email]>
Sent: Thursday, December 10, 2015 3:19 PM
To: 'Jason Mehrens'; 'concurrency-interest'
Subject: RE: [concurrency-interest] Enhance TimeoutException to include more    details

Hi Jason,

What you propose is a diagnostic capability which is way beyond what a
simple exception should be involved in. It simply isn't the role of
TimeoutException to try and expose all that.

How hard is it to gather that information when you detect the
TimeoutException? There are a couple of API's that could be used.

Cheers,
David

> -----Original Message-----
> From: [hidden email] [mailto:concurrency-
> [hidden email]] On Behalf Of Jason Mehrens
> Sent: Friday, December 11, 2015 4:27 AM
> To: concurrency-interest
> Subject: [concurrency-interest] Enhance TimeoutException to include
> more details
>
> Hello Concurrency-interest,
>
> A lot of the synchronizers included in jsr166 that throw
> TimeoutException do not include the information that is useful to know
> when such an event occurs. I'm assuming that performance, keeping the
> code simple, and not crippling evolution of the code are the main
> drivers for the way it is today.
>
> With those goals in mind, could TimeoutException be modified to
> include:
> 1. Information about the timeout value with a time unit mapped to
> getMessage().
> 2. A cause Throwable that contained the current stacktrace of the
> 'owner' thread (ASQ.getExclusiveOwnerThread().getStackTrace()).
> 3. Suppressed exceptions that contained all of the threads waiting to
> acquire (ASQ.getQueuedThreads())
>
>
> For example, if take a FutureTask with 4 threads:
> 1. A thread calls FutureTask.run
> 2. Two threads call FutureTask.get.
> 3. One thread calls FutureTask.get(1, SECONDS) and logs the timeout.
>
>
> To convert the stacktraces to a Throwable I abused the
> IllegalStateException for a proof of concept (no security manager).
> The timeout could be described using the following (hopefully the
> formatting works).
>
> =======================================================================
> ==========
> java.util.concurrent.TimeoutException: 1 SECONDS
>     at java.util.concurrent.FutureTask.get(FutureTask.java:205)
>     at
> TimeoutExampleOutput.testFutureTask(TimeoutExampleOutput.java:46)
>     at TimeoutExampleOutput.main(TimeoutExampleOutput.java:12)
>     Suppressed: java.lang.IllegalStateException: [14-WAITING-
> Thread[pool-1-thread-2,5,main]]
>         at sun.misc.Unsafe.park(Native Method)
>         at
> java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
>         at
> java.util.concurrent.FutureTask.awaitDone(FutureTask.java:429)
>         at java.util.concurrent.FutureTask.get(FutureTask.java:191)
>         at TimeoutExampleOutput$2.run(TimeoutExampleOutput.java:37)
>         at java.lang.Thread.run(Thread.java:745)
>     Suppressed: java.lang.IllegalStateException: [15-WAITING-
> Thread[pool-1-thread-3,5,main]]
>         at sun.misc.Unsafe.park(Native Method)
>         at
> java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
>         at
> java.util.concurrent.FutureTask.awaitDone(FutureTask.java:429)
>         at java.util.concurrent.FutureTask.get(FutureTask.java:191)
>         at TimeoutExampleOutput$2.run(TimeoutExampleOutput.java:37)
>         at java.lang.Thread.run(Thread.java:745)
> Caused by: java.lang.IllegalStateException: [13-TIMED_WAITING-
> Thread[pool-1-thread-1,5,main]]
>     at java.lang.Thread.sleep(Native Method)
>     at TimeoutExampleOutput$1.call(TimeoutExampleOutput.java:19)
>     at TimeoutExampleOutput$1.call(TimeoutExampleOutput.java:16)
>     at java.util.concurrent.FutureTask.run(FutureTask.java:266)
>     at java.lang.Thread.run(Thread.java:745)
> =======================================================================
> ===========
>
> The state of all 4 threads is described in this one failure.  You can
> see that this thread timed out was caused by the worker taking a nap
> and everyone else is being held up because of it.
>
> I would assume there is a way to capture some of this state in
> TimeoutException and then delay the evaluation of that state until some
> TimeoutException method is called like getCause or getMessage and
> retain most of the performance goals.  Or perhaps adding a method to
> TimeoutException to opt into this information.
>
> Any thoughts on this?
>
> Regards,
>
> Jason
>
> _______________________________________________
> Concurrency-interest mailing list
> [hidden email]
> http://cs.oswego.edu/mailman/listinfo/concurrency-interest


_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|

Re: Enhance TimeoutException to include more details

David Holmes-6
Jason Mehrens writes:
>
> Yes the role of TimeoutException is what I'm asking so you have
> answered my question.  The interesting part is that receiver of a
> timeout exception is usually a victim which means the information
> contained in the timeout exception is almost useless.  You have to
> admit that we set the bar pretty low when we don't even give back the
> value of the timeout.  I suppose that could lead to users coding
> parsers for that information.

I would expect the TimeoutException to be caught at the same level where the
timeout was set - certainly I would expect the value of the timeout used to
be available in most cases. If the exception is propagated to a level that
was unaware of the blocking operation then that seems a flaw in the error
propagation aspect of the API design. The actual value of the timeout is
also somewhat meaningless if you are not in code that understands it is
there and can do something to modify it. Also in many cases the actual
time-left-to-wait that is passed into a blocking operation is not the
maximum-time-to-wait that came in from the caller, so reporting it is again
somewhat meaningless in general.

 
> Using the example of FutureTask there are no (nor should there be)
> accessors to get the id or the actual runner of the FutureTask.  So
> gathering all the information for a JVM is not too hard.  Gathering the
> exact information for this specific synchronizer very difficult.
> Because of where TimeoutException is constructed it would have safe
> access to all the context required including the assailant thread.
> Even if TimeoutException had a methods that returned
> getExclusiveOwnerThread().getId() and ids of the getQueuedThreads would
> at add some utility without adding diagnostics directly.

I hear what you are saying but a TimeoutException is not a privileged member
of a synchronizer for which access to synchronizer innards can be provided

Exploring better diagnostic options for synchronizers is certainly something
to be considered.

Cheers,
David
 

> Jason
>
>
>
>
> ________________________________________
> From: David Holmes <[hidden email]>
> Sent: Thursday, December 10, 2015 3:19 PM
> To: 'Jason Mehrens'; 'concurrency-interest'
> Subject: RE: [concurrency-interest] Enhance TimeoutException to include
> more    details
>
> Hi Jason,
>
> What you propose is a diagnostic capability which is way beyond what a
> simple exception should be involved in. It simply isn't the role of
> TimeoutException to try and expose all that.
>
> How hard is it to gather that information when you detect the
> TimeoutException? There are a couple of API's that could be used.
>
> Cheers,
> David
>
> > -----Original Message-----
> > From: [hidden email] [mailto:concurrency-
> > [hidden email]] On Behalf Of Jason Mehrens
> > Sent: Friday, December 11, 2015 4:27 AM
> > To: concurrency-interest
> > Subject: [concurrency-interest] Enhance TimeoutException to include
> > more details
> >
> > Hello Concurrency-interest,
> >
> > A lot of the synchronizers included in jsr166 that throw
> > TimeoutException do not include the information that is useful to
> know
> > when such an event occurs. I'm assuming that performance, keeping the
> > code simple, and not crippling evolution of the code are the main
> > drivers for the way it is today.
> >
> > With those goals in mind, could TimeoutException be modified to
> > include:
> > 1. Information about the timeout value with a time unit mapped to
> > getMessage().
> > 2. A cause Throwable that contained the current stacktrace of the
> > 'owner' thread (ASQ.getExclusiveOwnerThread().getStackTrace()).
> > 3. Suppressed exceptions that contained all of the threads waiting to
> > acquire (ASQ.getQueuedThreads())
> >
> >
> > For example, if take a FutureTask with 4 threads:
> > 1. A thread calls FutureTask.run
> > 2. Two threads call FutureTask.get.
> > 3. One thread calls FutureTask.get(1, SECONDS) and logs the timeout.
> >
> >
> > To convert the stacktraces to a Throwable I abused the
> > IllegalStateException for a proof of concept (no security manager).
> > The timeout could be described using the following (hopefully the
> > formatting works).
> >
> >
> =======================================================================
> > ==========
> > java.util.concurrent.TimeoutException: 1 SECONDS
> >     at java.util.concurrent.FutureTask.get(FutureTask.java:205)
> >     at
> > TimeoutExampleOutput.testFutureTask(TimeoutExampleOutput.java:46)
> >     at TimeoutExampleOutput.main(TimeoutExampleOutput.java:12)
> >     Suppressed: java.lang.IllegalStateException: [14-WAITING-
> > Thread[pool-1-thread-2,5,main]]
> >         at sun.misc.Unsafe.park(Native Method)
> >         at
> > java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
> >         at
> > java.util.concurrent.FutureTask.awaitDone(FutureTask.java:429)
> >         at java.util.concurrent.FutureTask.get(FutureTask.java:191)
> >         at TimeoutExampleOutput$2.run(TimeoutExampleOutput.java:37)
> >         at java.lang.Thread.run(Thread.java:745)
> >     Suppressed: java.lang.IllegalStateException: [15-WAITING-
> > Thread[pool-1-thread-3,5,main]]
> >         at sun.misc.Unsafe.park(Native Method)
> >         at
> > java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
> >         at
> > java.util.concurrent.FutureTask.awaitDone(FutureTask.java:429)
> >         at java.util.concurrent.FutureTask.get(FutureTask.java:191)
> >         at TimeoutExampleOutput$2.run(TimeoutExampleOutput.java:37)
> >         at java.lang.Thread.run(Thread.java:745)
> > Caused by: java.lang.IllegalStateException: [13-TIMED_WAITING-
> > Thread[pool-1-thread-1,5,main]]
> >     at java.lang.Thread.sleep(Native Method)
> >     at TimeoutExampleOutput$1.call(TimeoutExampleOutput.java:19)
> >     at TimeoutExampleOutput$1.call(TimeoutExampleOutput.java:16)
> >     at java.util.concurrent.FutureTask.run(FutureTask.java:266)
> >     at java.lang.Thread.run(Thread.java:745)
> >
> =======================================================================
> > ===========
> >
> > The state of all 4 threads is described in this one failure.  You can
> > see that this thread timed out was caused by the worker taking a nap
> > and everyone else is being held up because of it.
> >
> > I would assume there is a way to capture some of this state in
> > TimeoutException and then delay the evaluation of that state until
> some
> > TimeoutException method is called like getCause or getMessage and
> > retain most of the performance goals.  Or perhaps adding a method to
> > TimeoutException to opt into this information.
> >
> > Any thoughts on this?
> >
> > Regards,
> >
> > Jason
> >
> > _______________________________________________
> > Concurrency-interest mailing list
> > [hidden email]
> > http://cs.oswego.edu/mailman/listinfo/concurrency-interest
>
>
> _______________________________________________
> Concurrency-interest mailing list
> [hidden email]
> http://cs.oswego.edu/mailman/listinfo/concurrency-interest

_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest