Dgraph4J under GraalVM native image segfault


Report a Dgraph Client Bug

What Dgraph client (and version) are you using?

(put “x” in the box to select)

  • Dgo
  • PyDgraph
  • Dgraph4J
  • Dgraph-js
  • Dgraph-js-http
  • Dgraph.NET

Version: v21.03.0

What version of Dgraph are you using?

v21.03.0

Have you tried reproducing the issue with the latest release?

yes

What is the hardware spec (RAM, OS)?

Linux under GKE

Steps to reproduce the issue (command/config used to run Dgraph).

I’ve used Dgraph4J in Micronaut project, added additional options to native-image gradle task:

    args("-H:ReflectionConfigurationFiles=reflect.json")
    args("-Dio.netty.leakDetection.level=DISABLED")
    args("-Dio.netty.noUnsafe=true")

reflect.json:

[
  {
    "name": "io.grpc.netty.shaded.io.netty.channel.socket.nio.NioSocketChannel",
    "methods": [
      {
        "name": "<init>",
        "parameterTypes": []
      }
    ]
  },
  {
    "name": "io.netty.util.internal.shaded.org.jctools.queues.MpscArrayQueueProducerIndexField",
    "fields": [
      {
        "name": "producerIndex",
        "allowUnsafeAccess": true
      }
    ]
  },
  {
    "name": "io.netty.util.internal.shaded.org.jctools.queues.MpscArrayQueueProducerLimitField",
    "fields": [
      {
        "name": "producerLimit",
        "allowUnsafeAccess": true
      }
    ]
  },
  {
    "name": "io.netty.util.internal.shaded.org.jctools.queues.MpscArrayQueueConsumerIndexField",
    "fields": [
      {
        "name": "consumerIndex",
        "allowUnsafeAccess": true
      }
    ]
  },
  {
    "name": "io.netty.util.internal.shaded.org.jctools.queues.BaseMpscLinkedArrayQueueProducerFields",
    "fields": [
      {
        "name": "producerIndex",
        "allowUnsafeAccess": true
      }
    ]
  },
  {
    "name": "io.netty.util.internal.shaded.org.jctools.queues.BaseMpscLinkedArrayQueueColdProducerFields",
    "fields": [
      {
        "name": "producerLimit",
        "allowUnsafeAccess": true
      }
    ]
  },
  {
    "name": "io.netty.util.internal.shaded.org.jctools.queues.BaseMpscLinkedArrayQueueConsumerFields",
    "fields": [
      {
        "name": "consumerIndex",
        "allowUnsafeAccess": true
      }
    ]
  },
  {
    "name": "io.netty.buffer.AbstractByteBufAllocator",
    "allDeclaredConstructors" : true,
    "allPublicConstructors" : true,
    "allDeclaredMethods" : true,
    "allPublicMethods" : true
  },
  {
    "name": "io.grpc.netty.shaded.io.netty.util.internal.shaded.org.jctools.queues.MpscArrayQueueProducerIndexField",
    "fields": [
      {
        "name": "producerIndex",
        "allowUnsafeAccess": true
      }
    ]
  },
  {
    "name": "io.grpc.netty.shaded.io.netty.util.internal.shaded.org.jctools.queues.MpscArrayQueueProducerLimitField",
    "fields": [
      {
        "name": "producerLimit",
        "allowUnsafeAccess": true
      }
    ]
  },
  {
    "name": "io.grpc.netty.shaded.io.netty.util.internal.shaded.org.jctools.queues.MpscArrayQueueConsumerIndexField",
    "fields": [
      {
        "name": "consumerIndex",
        "allowUnsafeAccess": true
      }
    ]
  },
  {
    "name": "io.grpc.netty.shaded.io.netty.util.internal.shaded.org.jctools.queues.BaseMpscLinkedArrayQueueProducerFields",
    "fields": [
      {
        "name": "producerIndex",
        "allowUnsafeAccess": true
      }
    ]
  },
  {
    "name": "io.grpc.netty.shaded.io.netty.util.internal.shaded.org.jctools.queues.BaseMpscLinkedArrayQueueColdProducerFields",
    "fields": [
      {
        "name": "producerLimit",
        "allowUnsafeAccess": true
      }
    ]
  },
  {
    "name": "io.grpc.netty.shaded.io.netty.util.internal.shaded.org.jctools.queues.BaseMpscLinkedArrayQueueConsumerFields",
    "fields": [
      {
        "name": "consumerIndex",
        "allowUnsafeAccess": true
      }
    ]
  },
  {
    "name": "io.grpc.netty.shaded.io.netty.buffer.AbstractByteBufAllocator",
    "allDeclaredConstructors" : true,
    "allPublicConstructors" : true,
    "allDeclaredMethods" : true,
    "allPublicMethods" : true
  }, {
    "name": "io.grpc.netty.shaded.io.netty.util.internal.shaded.org.jctools.util.UnsafeAccess",
    "allDeclaredConstructors" : true,
    "allPublicConstructors" : true,
    "allDeclaredMethods" : true,
    "allPublicMethods" : true
  }
]

Substitutions:

@TargetClass(io.grpc.netty.shaded.io.netty.buffer.AbstractByteBufAllocator.class)
final class Target_io_grpc_netty_shaded_io_netty_buffer_AbstractByteBufAllocator {
  @Substitute
  protected static io.grpc.netty.shaded.io.netty.buffer.ByteBuf toLeakAwareBuffer(
      io.grpc.netty.shaded.io.netty.buffer.ByteBuf buf) {
    return buf;
  }
}
@TargetClass(className = "io.grpc.netty.shaded.io.netty.util.internal.shaded.org.jctools.util.UnsafeAccess")
final class Target_io_grpc_netty_shaded_io_netty_util_internal_shaded_org_jctools_util_UnsafeAccess {
  @Substitute
  protected static long fieldOffset(Class clz, String fieldName) {
    return 0L;
  }
}

Expected behaviour and actual result.

Expected to work, but fails with segmentation fault on schema alter:

[ [ SubstrateSegfaultHandler caught a segfault. ] ]
...
...
SP 00007f8c20cfe8f0 IP 00000000012eb902 com.oracle.svm.core.code.CodeInfo@0x7f8c232b7b60 name = image code
SP 00007f8c20cfe920 IP 00000000012e975c [image code] io.grpc.netty.shaded.io.netty.util.concurrent.SingleThreadEventExecutor.addTask(SingleThreadEventExecutor.java:346)
SP 00007f8c20cfe950 IP 00000000012eae86 [image code] io.grpc.netty.shaded.io.netty.util.concurrent.SingleThreadEventExecutor.execute(SingleThreadEventExecutor.java:828)
SP 00007f8c20cfe990 IP 00000000012eb571 [image code] io.grpc.netty.shaded.io.netty.util.concurrent.SingleThreadEventExecutor.lazyExecute(SingleThreadEventExecutor.java:823)
SP 00007f8c20cfe9b0 IP 00000000012ce1d2 [image code] io.grpc.netty.shaded.io.netty.util.concurrent.AbstractScheduledEventExecutor.schedule(AbstractScheduledEventExecutor.java:263)
SP 00007f8c20cfe9f0 IP 00000000012ce67c [image code] io.grpc.netty.shaded.io.netty.util.concurrent.AbstractScheduledEventExecutor.schedule(AbstractScheduledEventExecutor.java:177)
SP 00007f8c20cfea40 IP 00000000012ccab4 [image code] io.grpc.netty.shaded.io.netty.util.concurrent.AbstractEventExecutorGroup.schedule(AbstractEventExecutorGroup.java:50)
SP 00007f8c20cfea70 IP 00000000012ccb43 [image code] io.grpc.netty.shaded.io.netty.util.concurrent.AbstractEventExecutorGroup.schedule(AbstractEventExecutorGroup.java:32)
SP 00007f8c20cfea80 IP 00000000010148b1 [image code] io.grpc.internal.Rescheduler.reschedule(Rescheduler.java:63)
SP 00007f8c20cfeab0 IP 00000000010002f6 [image code] io.grpc.internal.ManagedChannelImpl.rescheduleIdleTimer(ManagedChannelImpl.java:428)
SP 00007f8c20cfeac0 IP 0000000000ffe467 [image code] io.grpc.internal.ManagedChannelImpl.exitIdleMode(ManagedChannelImpl.java:386)
SP 00007f8c20cfeaf0 IP 0000000000ff2f72 [image code] io.grpc.internal.ManagedChannelImpl$RealChannel$1.run(ManagedChannelImpl.java:918)
SP 00007f8c20cfeb00 IP 0000000000fa7b7c [image code] io.grpc.SynchronizationContext.drain(SynchronizationContext.java:95)
SP 00007f8c20cfeb20 IP 0000000000fa7d46 [image code] io.grpc.SynchronizationContext.execute(SynchronizationContext.java:127)
SP 00007f8c20cfeb40 IP 0000000000ff4b7c [image code] io.grpc.internal.ManagedChannelImpl$RealChannel.newCall(ManagedChannelImpl.java:915)
SP 00007f8c20cfeb90 IP 0000000000fd2a05 [image code] io.grpc.internal.ManagedChannelImpl.newCall(ManagedChannelImpl.java:880)
SP 00007f8c20cfeb90 IP 0000000000fd2a05 [image code] io.grpc.internal.ForwardingManagedChannel.newCall(ForwardingManagedChannel.java:63)
SP 00007f8c20cfeba0 IP 0000000000f2eb63 [image code] io.dgraph.DgraphGrpc$DgraphStub.alter(DgraphGrpc.java:353)

Maybe it’s more netty-grpc issue then Dgraph, but please if anybody can confirm there’s a way to make Dgraph4J work under GraalVM native image…

@abhimanyusinghgaur could you please look into it thanks

Yeah! looks like something with grpc-netty.

I have personally never tried Dgraph4j with GraalVM before and am low on time. Can try this when I get a breather.

If anyone from the community can help, would be really awesome.
OR @denis111 if you ever figure this out, please let us know how to do it.

Thanks