ponyc: EXC_BAD_ACCESS crash in try_gc when under heavy load

I’m getting this intermittent error when sending load into a simple web server I created in Pony.

(lldb) target create "./pony0.10.0"
Current executable set to './pony0.10.0' (x86_64).
(lldb) settings set -- target.run-args  "8080"
(lldb) r
Process 19060 launched: './pony0.10.0' (x86_64)
Listening on ::1:8080
Process 19060 stopped
* thread #2: tid = 0x67912, 0x0000000100036e06 pony0.10.0`pony_traceunknown + 9, stop reason = EXC_BAD_ACCESS (code=1, address=0x74736fa8)
    frame #0: 0x0000000100036e06 pony0.10.0`pony_traceunknown + 9
pony0.10.0`pony_traceunknown:
->  0x100036e06 <+9>:  cmpq   $0x0, 0x40(%rdx)
    0x100036e0b <+14>: je     0x100036e14               ; <+23>
    0x100036e0d <+16>: movq   0x18(%rdi), %rax
    0x100036e11 <+20>: popq   %rbp
(lldb) bt
* thread #2: tid = 0x67912, 0x0000000100036e06 pony0.10.0`pony_traceunknown + 9, stop reason = EXC_BAD_ACCESS (code=1, address=0x74736fa8)
  * frame #0: 0x0000000100036e06 pony0.10.0`pony_traceunknown + 9
    frame #1: 0x0000000100001f26 pony0.10.0`Array_u3_t2_String_val_String_val_collections__MapEmpty_val_collections__MapDeleted_val_Trace + 118
    frame #2: 0x00000001000361cc pony0.10.0`ponyint_gc_handlestack + 70
    frame #3: 0x00000001000329f5 pony0.10.0`try_gc + 249
    frame #4: 0x000000010003868e pony0.10.0`run_thread + 280
    frame #5: 0x00007fffcc735aab libsystem_pthread.dylib`_pthread_body + 180
    frame #6: 0x00007fffcc7359f7 libsystem_pthread.dylib`_pthread_start + 286
    frame #7: 0x00007fffcc7351fd libsystem_pthread.dylib`thread_start + 13

Here is the minified version of code I’m running.

use "net/http"
use "time"

actor Main
    new create(env: Env) =>
    let service = try env.args(1) else "50000" end
    let logger = DiscardLog
    let handler = Handler.create("1") //.create(redis)

    let auth = try
      env.root as AmbientAuth
    else
      env.out.print("unable to use network")
      return
    end

    Server(auth, Info(env), handler, logger
      where service=service, reversedns=auth
    )

class Info
  let _env: Env

  new iso create(env: Env) => _env = env

  fun listening(server: Server ref) =>
    try
      (let host, let service) = server.local_address().name()
      _env.out.print("Listening on " + host + ":" + service)
    else
      server.dispose()
    end

  fun not_listening(server: Server ref) => None

  fun closed(server: Server ref) => None

class Handler is RequestHandler
  let _x: String val

  new val create(x: String val) =>
    _x = x

  fun now(): String =>
    Date(where seconds=Time.seconds())
    .format("%FT%TZ")
  fun apply(request: Payload) =>
    let result: String =
      match request.url.path
        | "/nr" => now()
        else "ponyc thinks it can get here. It can't!"
      end

    let response = Payload.response()
    response.add_chunk(result)
    response.add_chunk("\n")

    (consume request).respond(consume response)

Repeatedly running wrk with following options produce the issue.

wrk -t3 -c800 -d30s http://127.0.0.1:8080/nr

Information about my environment.

$ uname -a
Darwin Admins-MacBook-Pro.local 16.3.0 Darwin Kernel Version 16.3.0: Thu Nov 17 20:23:58 PST 2016; root:xnu-3789.31.2~1/RELEASE_X86_64 x86_64

$ ponyc --version
0.10.0 [release]
compiled with: llvm 3.9.0 -- Apple LLVM version 8.0.0 (clang-800.0.42.1)

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Reactions: 1
  • Comments: 34 (13 by maintainers)

Commits related to this issue

Most upvoted comments

Fix for this has been released as part of 0.14.0

I can confirm on MacOS 16.4.0

$ ponyc --version
0.12.3-0040b85a8 [debug]
compiled with: llvm 3.9.1 -- Apple LLVM version 8.1.0 (clang-802.0.38)
Process 3628 stopped
* thread #2, stop reason = EXC_BAD_ACCESS (code=1, address=0x8)
    frame #0: 0x0000000100028749 httpserver`ponyint_gc_release(gc=0x00000001197f02a8, aref=0x0000000118d69840) at gc.c:671
   668 	    void* p = obj->address;
   669 	    object_t* obj_local = ponyint_objectmap_getobject(&gc->local, p, &index);
   670 	
-> 671 	    pony_assert(obj_local->rc >= obj->rc);
   672 	    obj_local->rc -= obj->rc;
   673 	  }
   674