From a142e1c73f28acd82da02b9d41f7ada2df653d37 Mon Sep 17 00:00:00 2001 From: Thomas Hille Date: Wed, 22 Mar 2017 17:30:20 +0100 Subject: [PATCH 1/3] save messages returned from runs --- app/controllers/submissions_controller.rb | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/app/controllers/submissions_controller.rb b/app/controllers/submissions_controller.rb index 361ed866..2c7ed9f2 100644 --- a/app/controllers/submissions_controller.rb +++ b/app/controllers/submissions_controller.rb @@ -13,6 +13,10 @@ class SubmissionsController < ApplicationController before_action :set_mime_type, only: [:download_file, :render_file] skip_before_action :verify_authenticity_token, only: [:download_file, :render_file] + def max_message_buffer_size + 500 + end + def authorize! authorize(@submission || @submissions) end @@ -172,15 +176,21 @@ class SubmissionsController < ApplicationController end def handle_message(message, tubesock, container) + @message_buffer ||= "" # Handle special commands first if (/^#exit/.match(message)) kill_socket(tubesock) + @docker_client.exit_container(container) + if !@message_buffer.blank? + Testrun.create(file: @file, submission: @submission, output: @message_buffer) + end else # Filter out information about run_command, test_command, user or working directory run_command = @submission.execution_environment.run_command % command_substitutions(params[:filename]) test_command = @submission.execution_environment.test_command % command_substitutions(params[:filename]) if !(/root|workspace|#{run_command}|#{test_command}/.match(message)) + @message_buffer += message if @message_buffer.size <= max_message_buffer_size parse_message(message, 'stdout', tubesock) end end From 0930cba095924a9ce557265b27fee8385db91ed6 Mon Sep 17 00:00:00 2001 From: Ralf Teusner Date: Thu, 23 Mar 2017 14:12:26 +0100 Subject: [PATCH 2/3] changed position of saving the run output, so it catches timeouts as well --- app/controllers/submissions_controller.rb | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/app/controllers/submissions_controller.rb b/app/controllers/submissions_controller.rb index 2c7ed9f2..5c9978b7 100644 --- a/app/controllers/submissions_controller.rb +++ b/app/controllers/submissions_controller.rb @@ -143,7 +143,7 @@ class SubmissionsController < ApplicationController tubesock.onmessage do |data| Rails.logger.info(Time.now.getutc.to_s + ": Client sending: " + data) # Check whether the client send a JSON command and kill container - # if the command is 'client_exit', send it to docker otherwise. + # if the command is 'client_kill', send it to docker otherwise. begin parsed = JSON.parse(data) if parsed['cmd'] == 'client_kill' @@ -170,6 +170,9 @@ class SubmissionsController < ApplicationController end def kill_socket(tubesock) + # save the output of this "run" as a "testrun" (scoring runs are saved in submission_scoring.rb) + save_run_output + # Hijacked connection needs to be notified correctly tubesock.send_data JSON.dump({'cmd' => 'exit'}) tubesock.close @@ -238,6 +241,12 @@ class SubmissionsController < ApplicationController end end + def save_run_output + if !@message_buffer.blank? + Testrun.create(file: @file, submission: @submission, output: @message_buffer) + end + end + def score hijack do |tubesock| Thread.new { EventMachine.run } unless EventMachine.reactor_running? && EventMachine.reactor_thread.alive? From bdbc372c0c12d73f8c3fb4d653b52af0d980b4e0 Mon Sep 17 00:00:00 2001 From: Ralf Teusner Date: Fri, 24 Mar 2017 18:47:30 +0100 Subject: [PATCH 3/3] fixed saving run results. also fixed websocket closing. --- app/controllers/submissions_controller.rb | 12 +++++++----- lib/docker_client.rb | 7 +++++++ 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/app/controllers/submissions_controller.rb b/app/controllers/submissions_controller.rb index 5c9978b7..b9a1846e 100644 --- a/app/controllers/submissions_controller.rb +++ b/app/controllers/submissions_controller.rb @@ -182,12 +182,13 @@ class SubmissionsController < ApplicationController @message_buffer ||= "" # Handle special commands first if (/^#exit/.match(message)) - kill_socket(tubesock) - + # Just call exit_container on the docker_client. + # Do not call kill_socket for the websocket to the client here. + # @docker_client.exit_container closes the socket to the container, + # kill_socket is called in the "on close handler" of the websocket to the container @docker_client.exit_container(container) - if !@message_buffer.blank? - Testrun.create(file: @file, submission: @submission, output: @message_buffer) - end + elsif /^#timeout/.match(message) + @message_buffer = 'timeout: ' + @message_buffer # add information that this run timed out to the buffer else # Filter out information about run_command, test_command, user or working directory run_command = @submission.execution_environment.run_command % command_substitutions(params[:filename]) @@ -243,6 +244,7 @@ class SubmissionsController < ApplicationController def save_run_output if !@message_buffer.blank? + @message_buffer = @message_buffer[(0..max_message_buffer_size-1)] # trim the string to max_message_buffer_size chars Testrun.create(file: @file, submission: @submission, output: @message_buffer) end end diff --git a/lib/docker_client.rb b/lib/docker_client.rb index 28e2a3fb..76451096 100644 --- a/lib/docker_client.rb +++ b/lib/docker_client.rb @@ -255,6 +255,12 @@ class DockerClient if(@tubesock) @tubesock.send_data JSON.dump({'cmd' => 'timeout'}) end + if(@socket) + @socket.send('#timeout') + #sleep one more second to ensure that the message reaches the submissions_controller. + sleep(1) + @socket.close + end kill_container(container) end #ensure @@ -274,6 +280,7 @@ class DockerClient Rails.logger.debug('exiting container ' + container.to_s) # exit the timeout thread if it is still alive exit_thread_if_alive + @socket.close # if we use pooling and recylce the containers, put it back. otherwise, destroy it. (DockerContainerPool.config[:active] && RECYCLE_CONTAINERS) ? self.class.return_container(container, @execution_environment) : self.class.destroy_container(container) end