@@ -554,6 +554,7 @@ fiber_pool_expand(struct fiber_pool * fiber_pool, size_t count)
554554
555555 if (!VirtualProtect (page , RB_PAGE_SIZE , PAGE_READWRITE | PAGE_GUARD , & old_protect )) {
556556 VirtualFree (allocation -> base , 0 , MEM_RELEASE );
557+ ruby_xfree (allocation );
557558 rb_raise (rb_eFiberError , "can't set a guard page: %s" , ERRNOMSG );
558559 }
559560#elif defined(__wasi__ )
@@ -562,6 +563,7 @@ fiber_pool_expand(struct fiber_pool * fiber_pool, size_t count)
562563#else
563564 if (mprotect (page , RB_PAGE_SIZE , PROT_NONE ) < 0 ) {
564565 munmap (allocation -> base , count * stride );
566+ ruby_xfree (allocation );
565567 rb_raise (rb_eFiberError , "can't set a guard page: %s" , ERRNOMSG );
566568 }
567569#endif
@@ -666,13 +668,23 @@ fiber_pool_allocation_free(struct fiber_pool_allocation * allocation)
666668static struct fiber_pool_stack
667669fiber_pool_stack_acquire (struct fiber_pool * fiber_pool )
668670{
669- struct fiber_pool_vacancy * vacancy ;
671+ struct fiber_pool_vacancy * vacancy ;
672+
670673 RB_VM_LOCK_ENTER ();
671674 {
672675 vacancy = fiber_pool_vacancy_pop (fiber_pool );
673676
674677 if (DEBUG ) fprintf (stderr , "fiber_pool_stack_acquire: %p used=%" PRIuSIZE "\n" , (void * )fiber_pool -> vacancies , fiber_pool -> used );
675678
679+ // During allocation, if we run out of stacks, we may need to collect garbage to free up some stacks before trying to allocate more.
680+ if (!vacancy ) {
681+ if (DEBUG )fprintf (stderr , "fiber_pool_stack_acquire: no stacks available, collecting garbage\n" );
682+ rb_gc ();
683+
684+ // In the worst case, we garbage collect, but all fibers are reachable, so we don't free any stacks. We will try to expand the fiber pool:
685+ vacancy = fiber_pool_vacancy_pop (fiber_pool );
686+ }
687+
676688 if (!vacancy ) {
677689 const size_t maximum = FIBER_POOL_ALLOCATION_MAXIMUM_SIZE ;
678690 const size_t minimum = fiber_pool -> initial_count ;
@@ -681,6 +693,7 @@ fiber_pool_stack_acquire(struct fiber_pool * fiber_pool)
681693 if (count > maximum ) count = maximum ;
682694 if (count < minimum ) count = minimum ;
683695
696+ if (DEBUG )fprintf (stderr , "fiber_pool_stack_acquire: expanding fiber pool to %" PRIuSIZE " stacks\n" , count );
684697 fiber_pool_expand (fiber_pool , count );
685698
686699 // The free list should now contain some stacks:
0 commit comments