Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix hangs when deleting / recreating project root with the same name #548

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 20 additions & 2 deletions lib/spring/application_manager.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,11 @@ def restart
end

def alive?
@pid
return false if @pid.nil?
Process.getpgid(@pid)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems to be a reasonable way of determining whether a process with a certain pid exists.

true
rescue Errno::ESRCH
false
end

def with_child
Expand Down Expand Up @@ -109,10 +113,24 @@ def start_child(preload = false)
)
end

start_wait_thread(pid, child) if child.gets
wait_for_child_to_boot
start_wait_thread(pid, child)
rescue => e
log "error while starting child: #{e.message}"
abort("error while starting child: #{e.message}")
ensure
child_socket.close
end

def wait_for_child_to_boot
timeout = 1
loop do
break if IO.select([child], nil, nil, timeout)
Copy link
Contributor Author

@misterbyrne misterbyrne Dec 4, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The child process puts something on the socket to indicate that it's ready. Rather than simply wait forever as before (i.e. child.gets) we do the same, but check the process is still alive at 1 second intervals while doing so.

raise "child has exited unexpectedly" unless alive?
end
child.gets
end

def start_wait_thread(pid, child)
Process.detach(pid)

Expand Down
17 changes: 17 additions & 0 deletions lib/spring/test/acceptance_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,23 @@ def self.omg
assert_success app.spring_test_command
end

test "deleting the app root should kill the server" do
app.run app.spring_test_command
assert spring_env.server_running?, "The server should be running but it isn't"
FileUtils.rm_rf(app.root)
sleep 2 # wait for the watcher to notice and react
assert !spring_env.server_running?, "The server should not be running but it is"
end

test "server restarts when the app root is deleted and recreated" do
assert_success app.spring_test_command
FileUtils.rm_rf(app.root)
sleep 1 # wait for the watcher to notice and react

generator.copy_to(app.root)
assert_success app.spring_test_command
end

test "stop command kills server" do
app.run app.spring_test_command
assert spring_env.server_running?, "The server should be running but it isn't"
Expand Down