Show a localized message if the program was killed.

* This will most likely happen by the OOM killer, thus we inform the user about the memory restriction.
This commit is contained in:
Sebastian Serth
2022-04-15 21:29:55 +02:00
parent 5f7838ef46
commit 19bd742bc9
10 changed files with 37 additions and 7 deletions

View File

@ -743,6 +743,13 @@ var CodeOceanEditor = {
}); });
}, },
showOutOfMemoryMessage: function () {
$.flash.info({
icon: ['fa', 'fa-clock-o'],
text: $('#editor').data('message-out-of-memory')
});
},
showTimeoutMessage: function () { showTimeoutMessage: function () {
$.flash.info({ $.flash.info({
icon: ['fa', 'fa-clock-o'], icon: ['fa', 'fa-clock-o'],

View File

@ -102,6 +102,11 @@ CodeOceanEditorEvaluation = {
})) { })) {
this.showTimeoutMessage(); this.showTimeoutMessage();
} }
if (_.some(response, function (result) {
return result.status === 'out_of_memory';
})) {
this.showOutOfMemoryMessage();
}
if (_.some(response, function (result) { if (_.some(response, function (result) {
return result.status === 'container_depleted'; return result.status === 'container_depleted';
})) { })) {

View File

@ -47,6 +47,7 @@ CodeOceanEditorWebsocket = {
this.websocket.on('render', this.renderWebsocketOutput.bind(this)); this.websocket.on('render', this.renderWebsocketOutput.bind(this));
this.websocket.on('exit', this.handleExitCommand.bind(this)); this.websocket.on('exit', this.handleExitCommand.bind(this));
this.websocket.on('timeout', this.showTimeoutMessage.bind(this)); this.websocket.on('timeout', this.showTimeoutMessage.bind(this));
this.websocket.on('out_of_memory', this.showOutOfMemoryMessage.bind(this));
this.websocket.on('status', this.showStatus.bind(this)); this.websocket.on('status', this.showStatus.bind(this));
this.websocket.on('hint', this.showHint.bind(this)); this.websocket.on('hint', this.showHint.bind(this));
}, },

View File

@ -29,10 +29,14 @@ $(document).on('turbolinks:load', function () {
}; };
const handleResponse = function (response) { const handleResponse = function (response) {
// Always print stdout and stderr
printOutput(response);
// If an error occurred, print it too
if (response.status === 'timeout') { if (response.status === 'timeout') {
printTimeout(response); printTimeout(response);
} else { } else if (response.status === 'out_of_memory') {
printOutput(response); printOutOfMemory(response);
} }
}; };
@ -71,12 +75,19 @@ $(document).on('turbolinks:load', function () {
}; };
const printTimeout = function (output) { const printTimeout = function (output) {
const element = $.append('<p>'); const element = $('<p>');
element.addClass('text-danger'); element.addClass('text-danger');
element.text($('#shell').data('message-timeout')); element.text($('#shell').data('message-timeout'));
$('#output').append(element); $('#output').append(element);
}; };
const printOutOfMemory = function (output) {
const element = $('<p>');
element.addClass('text-danger');
element.text($('#shell').data('message-out-of-memory'));
$('#output').append(element);
};
if ($('#shell').isPresent()) { if ($('#shell').isPresent()) {
const command = $('#command') const command = $('#command')
command.focus(); command.focus();

View File

@ -157,6 +157,7 @@ class SubmissionsController < ApplicationController
"\n#{t('exercises.implement.exit_failure', timestamp: l(Time.zone.now, format: :short), exit_code: exit_code)}" "\n#{t('exercises.implement.exit_failure', timestamp: l(Time.zone.now, format: :short), exit_code: exit_code)}"
end end
client_socket.send_data JSON.dump({cmd: :write, stream: :stdout, data: "#{exit_statement}\n"}) client_socket.send_data JSON.dump({cmd: :write, stream: :stdout, data: "#{exit_statement}\n"})
client_socket.send_data JSON.dump({cmd: :out_of_memory}) if exit_code == 137
close_client_connection(client_socket) close_client_connection(client_socket)
end end

View File

@ -78,13 +78,14 @@ class Runner < ApplicationRecord
stdout = +'' stdout = +''
stderr = +'' stderr = +''
try = 0 try = 0
exit_code = 1 # default to error
begin begin
if try.nonzero? if try.nonzero?
request_new_id request_new_id
save save
end end
exit_code = 1 # default to error
execution_time = attach_to_execution(command) do |socket| execution_time = attach_to_execution(command) do |socket|
socket.on :stderr do |data| socket.on :stderr do |data|
stderr << data stderr << data
@ -120,7 +121,9 @@ class Runner < ApplicationRecord
# We forward the exception if requested # We forward the exception if requested
raise e if raise_exception && defined?(e) && e.present? raise e if raise_exception && defined?(e) && e.present?
output.merge!(stdout: stdout, stderr: stderr) # If the process was killed with SIGKILL, it is most likely that the OOM killer was triggered.
output[:status] = :out_of_memory if exit_code == 137
output.merge!(stdout: stdout, stderr: stderr, exit_code: exit_code)
end end
end end

View File

@ -1,6 +1,6 @@
h1 = @execution_environment h1 = @execution_environment
#shell data-message-timeout=t('exercises.editor.timeout', permitted_execution_time: @execution_environment.permitted_execution_time) data-url=execute_command_execution_environment_path(@execution_environment) #shell data-message-timeout=t('exercises.editor.timeout', permitted_execution_time: @execution_environment.permitted_execution_time) data-message-out-of-memory=t('exercises.editor.out_of_memory', memory_limit: @execution_environment.memory_limit) data-url=execute_command_execution_environment_path(@execution_environment)
.form-group .form-group
label for='command' = t('.command') label for='command' = t('.command')
input#command.form-control type='text' input#command.form-control type='text'

View File

@ -5,7 +5,7 @@
- show_rfc_interventions = @show_rfc_interventions || "false" - show_rfc_interventions = @show_rfc_interventions || "false"
- show_tips_interventions = @show_tips_interventions || "false" - show_tips_interventions = @show_tips_interventions || "false"
- hide_rfc_button = @hide_rfc_button || false - hide_rfc_button = @hide_rfc_button || false
#editor.row data-exercise-id=@exercise.id data-message-depleted=t('exercises.editor.depleted') data-message-timeout=t('exercises.editor.timeout', permitted_execution_time: @exercise.execution_environment.permitted_execution_time) data-submissions-url=submissions_path data-user-id=@current_user.id data-user-external-id=external_user_external_id data-working-times-url=working_times_exercise_path(@exercise) data-intervention-save-url=intervention_exercise_path(@exercise) data-rfc-interventions=show_rfc_interventions data-break-interventions=show_break_interventions data-tips-interventions=show_tips_interventions data-course_token=@course_token data-search-save-url=search_exercise_path(@exercise) #editor.row data-exercise-id=@exercise.id data-message-depleted=t('exercises.editor.depleted') data-message-timeout=t('exercises.editor.timeout', permitted_execution_time: @exercise.execution_environment.permitted_execution_time) data-message-out-of-memory=t('exercises.editor.out_of_memory', memory_limit: @exercise.execution_environment.memory_limit) data-submissions-url=submissions_path data-user-id=@current_user.id data-user-external-id=external_user_external_id data-working-times-url=working_times_exercise_path(@exercise) data-intervention-save-url=intervention_exercise_path(@exercise) data-rfc-interventions=show_rfc_interventions data-break-interventions=show_break_interventions data-tips-interventions=show_tips_interventions data-course_token=@course_token data-search-save-url=search_exercise_path(@exercise)
- unless @embed_options[:hide_sidebar] - unless @embed_options[:hide_sidebar]
- additional_classes = 'sidebar-col' - additional_classes = 'sidebar-col'

View File

@ -360,6 +360,7 @@ de:
submit_after_late_deadline: Code verspätet zur Bewertung abgeben submit_after_late_deadline: Code verspätet zur Bewertung abgeben
test: Testen test: Testen
timeout: 'Ausführung gestoppt. Ihr Code hat die erlaubte Ausführungszeit von %{permitted_execution_time} Sekunden überschritten.' timeout: 'Ausführung gestoppt. Ihr Code hat die erlaubte Ausführungszeit von %{permitted_execution_time} Sekunden überschritten.'
out_of_memory: 'Ausführung gestoppt. Ihr Code hat den erlaubten Arbeitsspeicher von %{memory_limit} MB überschritten.'
exercise_deadline_passed: 'Das Ergebnis kann nicht übertragen werden.' exercise_deadline_passed: 'Das Ergebnis kann nicht übertragen werden.'
tooltips: tooltips:
save: Ihr Code wird automatisch gespeichert, wann immer Sie eine Datei herunterladen, ausführen oder testen. Explizites Speichern ist also selten notwendig. save: Ihr Code wird automatisch gespeichert, wann immer Sie eine Datei herunterladen, ausführen oder testen. Explizites Speichern ist also selten notwendig.

View File

@ -360,6 +360,7 @@ en:
submit_after_late_deadline: Submit Code for Assessment After Deadline Passed submit_after_late_deadline: Submit Code for Assessment After Deadline Passed
test: Test test: Test
timeout: 'Execution stopped. Your code exceeded the permitted execution time of %{permitted_execution_time} seconds.' timeout: 'Execution stopped. Your code exceeded the permitted execution time of %{permitted_execution_time} seconds.'
out_of_memory: 'Execution stopped. Your code exceeded the permitted RAM usage of %{memory_limit} MB.'
exercise_deadline_passed: 'The score cannot be submitted.' exercise_deadline_passed: 'The score cannot be submitted.'
tooltips: tooltips:
save: Your code is automatically saved whenever you download, run, or test it. Therefore, explicitly saving is rarely necessary. save: Your code is automatically saved whenever you download, run, or test it. Therefore, explicitly saving is rarely necessary.