zio-http icon indicating copy to clipboard operation
zio-http copied to clipboard

IllegalReferenceCountException

Open rleibman opened this issue 3 years ago • 3 comments

Describe the bug When we upgraded from RC25 to RC27 our very simple server started throwing this exception

To Reproduce Sorry, not clear, it's a simple server, the request is a POST with json (circe) data, responding also with json data (though I don't think it gets that far)

Expected behaviour We shouldn't get an exception, and if we do, there should be clear logs.

Smartphone (please complete the following information):

  • Device: reproduced locally on IOS or ubuntu cloud

Additional context Hey... after we upgraded from RC25 to RC27, we started getting the following error:

Uncaught failure: io.netty.util.IllegalReferenceCountException: refCnt: 0

<init>:30, IllegalReferenceCountException (io.netty.util)
ensureAccessible:1454, AbstractByteBuf (io.netty.buffer)
checkIndex:1383, AbstractByteBuf (io.netty.buffer)
checkDstIndex:1409, AbstractByteBuf (io.netty.buffer)
getBytes:1062, CompositeByteBuf (io.netty.buffer)
getBytes:2031, CompositeByteBuf (io.netty.buffer)
getBytes:49, CompositeByteBuf (io.netty.buffer)
getBytes:1336, ByteBufUtil (io.netty.buffer)
getBytes:1309, ByteBufUtil (io.netty.buffer)
getBytes:1301, ByteBufUtil (io.netty.buffer)
$anonfun$bodyAsByteArray$2:21, HttpDataExtension (zhttp.http)
apply:-1, HttpDataExtension$$Lambda$2824/0x000000080121c0c8 (zhttp.http)
evaluateNow:496, FiberContext (zio.internal)
$anonfun$fork$15:781, FiberContext (zio.internal)
run:-1, FiberContext$$Lambda$220/0x0000000800e0eba0 (zio.internal)
safeExecute$$$capture:164, AbstractEventExecutor (io.netty.util.concurrent)
safeExecute:-1, AbstractEventExecutor (io.netty.util.concurrent)

BTW.... I couldn't detect any logging on this issue coming out of zhttp or netty, so I had to go into the debugger, put a breakpoint in the exception's constructor and capture the stack trace from there.

rleibman avatar Apr 14 '22 18:04 rleibman

Can you show use the code you are using to read the body? Also are you reading it more than once?

tusharmath avatar Apr 19 '22 04:04 tusharmath

              request <- req.bodyAsString.flatMap { str =>
                implicit val decoder: Decoder[MyRequest] = myRequestDecoder(now)

                (for {
                  json    <- parse(str)
                  request <- json.as[MyRequest]
                } yield request).fold(
                  e => ZIO.fail(BadRequestException(s"$str was not valid MyRequest: ${e.getMessage}")),
                  r => ZIO(r)
                )
              }

and yes, I think we're reading it more than once:

  final protected def logJsonRequest(req: Request): ZIO[Logging, Nothing, Unit] = {
    (for {
      body <- req.bodyAsString
      _    <- log.info(s"${req.method.toString()} request to ${req.url.encode}: " + parse(body).fold(_ => body, _.noSpaces))
    } yield ()).ignore
  }

rleibman avatar Apr 21 '22 21:04 rleibman

I think we should throw a more appropriate error in case the content is read more than once. For performance reasons we don't allow reading data more than once right now.

We can even add a few operators to decode and cache data, thus giving user flexibility over ease-of-use vs performance.

tusharmath avatar Apr 28 '22 07:04 tusharmath

This should be fixed in #1351.

tusharmath avatar Aug 29 '22 02:08 tusharmath