Skip to content

Controller breaks on SIGHUP when ready isn't explicitly called #14

Open
@bryanp

Description

@bryanp

Discussed this with @ioquatix on Slack. Reproduce with the example code from the readme:

require 'async/container'

class Controller < Async::Container::Controller
  def setup(container)
    container.async do |task|
      while true
        puts "hello"
        task.sleep(1)
      end
    end
  end
end

controller = Controller.new

controller.run

Send SIGHUP to the main process. You should see something like this in terminal:

zsh: hangup     bundle exec ruby readme.rb

"hello" is still printed because the child process is still running. Hitting Ctrl-C does not stop the process at this point. Stopping the process through Activity Monitor causes this error:

13.52s    error: Async::Container::Process [pid=5891] [2020-04-14 09:22:11 -0700]
               |   Async::Container::Terminate: SIGTERM
               |   → /Users/bryanp/.gem/ruby/2.6.5/gems/async-container-0.16.4/lib/async/container/process.rb:74 in `block (3 levels) in fork'
               |     /Users/bryanp/.gem/ruby/2.6.5/gems/async-1.24.2/lib/async/reactor.rb:204 in `select'
               |     /Users/bryanp/.gem/ruby/2.6.5/gems/async-1.24.2/lib/async/reactor.rb:204 in `run_once'
               |     /Users/bryanp/.gem/ruby/2.6.5/gems/async-1.24.2/lib/async/reactor.rb:234 in `run'
               |     /Users/bryanp/.gem/ruby/2.6.5/gems/async-1.24.2/lib/async/reactor.rb:56 in `run'
               |     /Users/bryanp/.gem/ruby/2.6.5/gems/async-container-0.16.4/lib/async/container/generic.rb:168 in `block in async'
               |     /Users/bryanp/.gem/ruby/2.6.5/gems/async-container-0.16.4/lib/async/container/process.rb:77 in `block (2 levels) in fork'
               |     /Users/bryanp/.gem/ruby/2.6.5/gems/async-container-0.16.4/lib/async/container/process.rb:72 in `fork'
               |     /Users/bryanp/.gem/ruby/2.6.5/gems/async-container-0.16.4/lib/async/container/process.rb:72 in `block in fork'
               |     /Users/bryanp/.gem/ruby/2.6.5/gems/async-container-0.16.4/lib/async/container/process.rb:106 in `initialize'
               |     /Users/bryanp/.gem/ruby/2.6.5/gems/async-container-0.16.4/lib/async/container/process.rb:71 in `new'
               |     /Users/bryanp/.gem/ruby/2.6.5/gems/async-container-0.16.4/lib/async/container/process.rb:71 in `fork'
               |     /Users/bryanp/.gem/ruby/2.6.5/gems/async-container-0.16.4/lib/async/container/forked.rb:35 in `start'
               |     /Users/bryanp/.gem/ruby/2.6.5/gems/async-container-0.16.4/lib/async/container/generic.rb:134 in `block in spawn'

Here's a working version:

require 'async/container'

class Controller < Async::Container::Controller
  def setup(container)
    container.run(count: 1) do |instance|
      Async do |task|
        task.async do
          loop do
            puts "hello"

            task.sleep 1
          end
        end

        instance.ready!

        task.children.each(&:wait)
      end
    end
  end
end

controller = Controller.new

controller.run

Couple observations:

  1. We should consider a better way to handle the case where ready! is not called.
  2. I'm not entirely sure how ready! is to be called when using container.async.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions