BUG: Process hang on M1
Opened this issue · 9 comments
This code will cause the process to go unresponsive and hang on an M1:
require "fswatch"
FSWatch.watch "." do |event|
puts "got event for #{event.path}"
end
I'm not sure if this is also an issue on other systems. I have fswatch installed from brew, and I didn't see anything in their issues which might indicate that it's related:
> brew info fswatch
==> fswatch: stable 1.17.1 (bottled)
FSWatch.watch
will not block the main fiber. I think the program is finishing right away.
Validated with
% crystal --version
Crystal 1.11.2 (2024-01-18)
LLVM: 17.0.6
Default target: aarch64-apple-darwin23.2.0
% brew info fswatch
==> fswatch: stable 1.17.1 (bottled)
macOS 14.2.1 (23C71)
FSWatch.watch will not block the main fiber. I think the program is finishing right away.
I'm also able to trip into the scenario while using Kemal to block the main fiber:
require "kemal"
require "fswatch"
FSWatch.watch "." do |event|
puts "got event for #{event.path}"
end
get "/" do |env|
"Hello World!"
end
Kemal.run
When I run watch -n 1 curl http://localhost:3000
I can see kemal responding to requests until a single FSWatch event fires, and then it gets blocked. This is how I ran into the bug myself, I should have posted the full context before.
Single thread or multi thread?
I'll try to repro tomorrow
Just single thread. I'm not doing anything fancy with mt. Thanks for looking.
It seems that there is an issue with crystal 1.11.x . The specs don't even finish to run which is consistent with your experience with kemal.
@robacarp can you check if crystal 1.10.x works for you until I can narrow it down better?
Call graph:
2490 Thread_45538412 DispatchQueue_1: com.apple.main-thread (serial)
+ 2490 start (in dyld) + 2360 [0x1884050e0]
+ 2490 main (in crystal-run-spec.tmp) + 12 [0x1045870a0] main.cr:141
+ 2490 *Crystal::main<Int32, Pointer(Pointer(UInt8))>:Int32 (in crystal-run-spec.tmp) + 108 [0x10476dd90] main.cr:59
+ 2490 *Crystal::exit<Int32, (Exception+ | Nil)>:Int32 (in crystal-run-spec.tmp) + 40 [0x10476de28] main.cr:64
+ 2490 *Crystal::AtExitHandlers::run<Int32, (Exception+ | Nil)>:Int32 (in crystal-run-spec.tmp) + 148 [0x1046cc844] at_exit_handlers.cr:14
+ 2490 ~procProc(Int32, (Exception | Nil), Nil)@/Users/bcardiff/Downloads/crystal-1.11.2-1/src/spec/dsl.cr:208 (in crystal-run-spec.tmp) + 76 [0x1045ed084] dsl.cr:216
+ 2490 *Spec::execute_examples:Nil (in crystal-run-spec.tmp) + 28 [0x1046f9d3c] dsl.cr:234
+ 2490 *Spec::RootContext#run:Nil (in crystal-run-spec.tmp) + 28 [0x104714e9c] context.cr:158
+ 2490 *Spec::RootContext@Spec::Context#internal_run:Nil (in crystal-run-spec.tmp) + 200 [0x104714f70] context.cr:18
+ 2490 *Spec::ExampleGroup#run:Nil (in crystal-run-spec.tmp) + 364 [0x10474500c] context.cr:340
+ 2490 *Spec::ExampleGroup@Spec::Context#internal_run:Nil (in crystal-run-spec.tmp) + 144 [0x10474516c] context.cr:18
+ 2490 *Spec::Example#run:Nil (in crystal-run-spec.tmp) + 1208 [0x104742340] example.cr:38
+ 2490 *Spec::Example#internal_run<Time::Span, Proc(Nil)>:(Array(Spec::Result) | Nil) (in crystal-run-spec.tmp) + 212 [0x104742444] example.cr:50
+ 2490 ~procProc(Nil)@spec/session_spec.cr:9 (in crystal-run-spec.tmp) + 708 [0x1045ee4f8] session_spec.cr:20
+ 2490 ~procProc(FSWatch::Session, Channel(FSWatch::Event), String, Nil)@spec/session_spec.cr:41 (in crystal-run-spec.tmp) + 192 [0x1045ed9fc] session_spec.cr:47
+ 2490 *File::join<String, String>:String (in crystal-run-spec.tmp) + 64 [0x1046a5d38] file.cr:852
+ 2490 *Path::new<String, String>:Path (in crystal-run-spec.tmp) + 64 [0x104661f8c] path.cr:109
+ 2490 *Path#join<String>:Path (in crystal-run-spec.tmp) + 872 [0x104662310] string.cr:254
+ 2490 *GC::malloc_atomic<UInt32>:Pointer(Void) (in crystal-run-spec.tmp) + 16 [0x10462fc70] gc.cr:88
+ 2490 *GC::malloc_atomic<UInt64>:Pointer(Void) (in crystal-run-spec.tmp) + 12 [0x10462fc84] boehm.cr:152
+ 2490 GC_malloc_kind_global (in crystal-run-spec.tmp) + 60 [0x1047f3048]
+ 2490 _pthread_mutex_firstfit_lock_slow (in libsystem_pthread.dylib) + 248 [0x188780af8]
+ 2490 _pthread_mutex_firstfit_lock_wait (in libsystem_pthread.dylib) + 84 [0x188783168]
+ 2490 __psynch_mutexwait (in libsystem_kernel.dylib) + 8 [0x188748524]
Specs are failing on Linux (Ubuntu 20.04, fswatch 1.14, Crystal 1.11.2) with or without preview_mt
: they detect nothing, so I can't reproduce.
FSWatch.watch will not block the main fiber. I think the program is finishing right away.
Same behavior. That's the expected behavior: watch
won't block. I added a sleep
and it's working correctly. Weirdly the specs won't pass 🤷
@bcardiff on Crystal 1.10.1, it is indeed working. That'll do fine for me, thank you!
(Half) Found it!
I bisected the problem to crystal-lang/crystal#14130
I am not sure why that is causing issues yet.
But the good thing is that at least for now you can monkey-patch your project with the following code and it should work with Crystal 1.11.x (and Crystal master)
lib LibGC
$stackbottom = GC_stackbottom : Void*
end
module GC
def self.current_thread_stack_bottom
{Pointer(Void).null, LibGC.stackbottom}
end
def self.set_stackbottom(stack_bottom : Void*)
LibGC.stackbottom = stack_bottom
end
end