Проблемы с запуском приложения в контролируемой среде (Win32) - PullRequest
0 голосов
/ 10 февраля 2009

Я не совсем уверен, как пометить этот вопрос или как написать заголовок, поэтому, если у кого-то есть идея получше, отредактируйте ее

Вот сделка:

Некоторое время назад я написал небольшую, но крайне важную часть вычислительной системы управления олимпиадами . Задача системы состоит в том, чтобы получать заявки от участников (файлы кода), компилировать их, запускать их в соответствии с заранее определенными тестовыми примерами и возвращать результаты. Плюс ко всему остальному, что вы можете себе представить.

Часть, которую я написал, называлась Limiter . Это была маленькая программа, задачей которой было взять другую программу и запустить ее в контролируемой среде. Управляемый в этом случае означает ограничения на доступную память, вычислительное время и доступ к системным ресурсам. Кроме того, в случае сбоя программы я смогу определить тип исключения и сообщить об этом пользователю. Кроме того, когда процесс завершается, следует отметить, как долго он выполняется (с разрешением не менее 0,01 секунды, лучше больше).

Конечно, идеальным решением для этого была бы виртуализация, но я не настолько опытен, чтобы писать это.

Мое решение было разделено на три части.

Самой простой частью был доступ к системным ресурсам. Программа будет просто выполняться с токенами с ограниченным доступом. Я объединил некоторые из базовых (Все, анонимные и т. Д.) Токенов доступа, которые доступны всем процессам, чтобы обеспечить практически доступ только для чтения к системе, за исключением папки, в которой она выполнялась.

Ограничение памяти было сделано через объекты заданий - они позволяют указать максимальный предел памяти.

И, наконец, чтобы ограничить время выполнения и перехватить все исключения, мой Limiter присоединяется к процессу как отладчик. Таким образом, я могу контролировать время, которое он провел, и прекратить его, если это займет слишком много времени. Обратите внимание, что я не могу использовать объекты Job для этого, потому что они сообщают только время ядра и время пользователя для задания. Процесс может сделать что-то вроде Sleep(99999999), которое не будет учитываться ни в одном из них, но все равно отключит машину тестирования. Таким образом, хотя я не учитываю время простоя процессов в его окончательном времени выполнения, оно все равно должно иметь ограничение.

Так вот, я не эксперт в подобных вещах низкого уровня. Я провел несколько дней, читая MSDN и играя, и придумал решение, как мог. К сожалению, кажется, что он работает не так хорошо, как можно было ожидать. По большей части это работает нормально, но странные случаи продолжают накапливаться. Сейчас у меня есть небольшая программа на C ++, которая работает за доли секунды, но мой Limiter сообщает о 8 секундах времени в режиме пользователя (взятых из счетчиков заданий). Вот код Он печатает вывод примерно за полсекунды, а затем тратит более 7 секунд на ожидание:

#include <iostream>
#include <vector>
using namespace std;

int main()
{
    vector< vector<int> > dp(50000, vector<int>(4, -1));
    cout << dp.size();
}

Код ограничителя довольно длинный, поэтому я его здесь не включаю. Я также чувствую, что может быть что-то не так с моим подходом - возможно, я не должен делать вещи отладчика. Возможно, есть некоторые распространенные подводные камни, о которых я не знаю.

Я хотел бы получить совет о том, как другие люди будут решать эту проблему. Возможно, что-то уже есть, и мой лимитер устарел?

<ч /> Добавлено: Проблема, похоже, в маленькой программе, которую я выложил выше. Я открыл для него новый вопрос , поскольку он несколько не связан. Я все еще хотел бы комментировать этот подход для ограничения программы.

1 Ответ

0 голосов
/ 06 сентября 2013

Запуск с подключенным отладчиком может изменить характеристики приложения. На производительность может повлиять, а пути к коду могут даже измениться (если целевой процесс делает что-то, основываясь на наличии отладчика, т.е.

Другой подход, который мы использовали, заключается в настройке нашего собственного приложения для работы в качестве отладчика JIT. Установив ключ реестра AeDebug, вы можете контролировать, какой отладчик вызывается при сбое приложения. Таким образом, вы подключаетесь только когда происходит сбой целевого процесса, и это не влияет на процесс во время нормальной работы.

Этот сайт содержит некоторые сведения о настройке отладчика после смерти: Настройка автоматической отладки .

Ваш подход к ограничению памяти, получению времени и т. Д. Звучит идеально.

...