| 325 | } |
| 326 | |
| 327 | public static Status statusFromThrowable(Throwable t) { |
| 328 | Status s = Status.fromThrowable(t); |
| 329 | if (s.getCode() != Status.Code.UNKNOWN) { |
| 330 | return s; |
| 331 | } |
| 332 | if (t instanceof ClosedChannelException) { |
| 333 | if (t.getCause() != null) { |
| 334 | // If the remote closes the connection while the event loop is processing, then a write or |
| 335 | // flush can be the first operation to notice the closure. Those exceptions are a |
| 336 | // ClosedChannelException, with a cause that provides more information, which is exactly |
| 337 | // what we'd hope for. |
| 338 | return Status.UNAVAILABLE.withDescription("channel closed").withCause(t); |
| 339 | } |
| 340 | // ClosedChannelException is used for all operations after the Netty channel is closed. But it |
| 341 | // doesn't have the original closure information. Proper error processing requires remembering |
| 342 | // the error that occurred before this one and using it instead. |
| 343 | // |
| 344 | // Netty uses an exception that has no stack trace, while we would never hope to show this to |
| 345 | // users, if it happens having the extra information may provide a small hint of where to |
| 346 | // look. |
| 347 | ClosedChannelException extraT = new ClosedChannelException(); |
| 348 | extraT.initCause(t); |
| 349 | return Status.UNKNOWN.withDescription("channel closed").withCause(extraT); |
| 350 | } |
| 351 | if (t instanceof DecoderException && t.getCause() instanceof SSLException) { |
| 352 | return Status.UNAVAILABLE.withDescription("ssl exception").withCause(t); |
| 353 | } |
| 354 | if (t instanceof IOException) { |
| 355 | return Status.UNAVAILABLE.withDescription("io exception").withCause(t); |
| 356 | } |
| 357 | if (t instanceof UnresolvedAddressException) { |
| 358 | return Status.UNAVAILABLE.withDescription("unresolved address").withCause(t); |
| 359 | } |
| 360 | if (t instanceof Http2Exception) { |
| 361 | return Status.INTERNAL.withDescription("http2 exception").withCause(t); |
| 362 | } |
| 363 | return s; |
| 364 | } |
| 365 | |
| 366 | @VisibleForTesting |
| 367 | static boolean isEpollAvailable() { |