def test_log_stderr(self): Utils.prepare_test(connect_logger=True) with Utils.nostderr() as err: Logger.error("FOO_CAT", "Log message") self.assertIn("FOO_CAT", err.buffer) self.assertIn("Log message", err.buffer)
def download_results(self): """ POST /admin/download_pack """ Logger.info("ADMIN", "Creating zip file") zip_directory = os.path.join(Config.storedir, "zips", Database.gen_id()) os.makedirs(zip_directory, exist_ok=True) zipf_name = ("results-" + Database.get_meta("admin_token").split("-", 1)[0] + "-" + time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime()) + ".zip") zipf_name = os.path.join(zip_directory, zipf_name) command = ("zip -r '" + zipf_name + "' db.sqlite3* log.sqlite3* " "files/input files/output " "files/source /version* " "/proc/cpuinfo* " "/var/log/nginx") try: gevent.subprocess.check_output(command, shell=True, stderr=subprocess.STDOUT) except subprocess.CalledProcessError as e: Logger.error("ADMIN", "Zip error: %s" % e.output) raise e return { "path": os.path.relpath(zipf_name, Config.storedir) } # pragma: nocover
def evaluate_output(task_name, input_path, output_path): """ Given an input of a task, evaluate the correctness of the output :param task_name: Name of the task :param input_path: Path to the user's input file :param output_path: Path to the user's output file :return: The stdout of the checker """ try: # call the checker and store the output start_time = time.monotonic() output = gevent.subprocess.check_output([ ContestManager.tasks[task_name]["checker"], StorageManager.get_absolute_path(input_path), StorageManager.get_absolute_path(output_path) ]) if time.monotonic() > start_time + 1: Logger.warning( "TASK", "Evaluation of output %s " "for task %s, with input %s, took %f " "seconds" % (output_path, task_name, input_path, time.monotonic() - start_time)) except: # TODO log the stdout and stderr of the checker Logger.error( "TASK", "Error while evaluating output %s " "for task %s, with input %s: %s" % (output_path, task_name, input_path, traceback.format_exc())) raise Logger.info( "TASK", "Evaluated output %s for task %s, with input %s" % (output_path, task_name, input_path)) return output
def run(self): """ Start a greenlet with the main HTTP server loop """ server = gevent.pywsgi.WSGIServer( (Config.address, Config.port), self, log=None) try: server.init_socket() except OSError: Logger.error("PORT_ALREADY_IN_USE", "Address: '%s' Port: %d" % (Config.address, Config.port)) sys.exit(1) greenlet = gevent.spawn(server.serve_forever) port = "" if Config.port == 80 else ":" + str(Config.port) Logger.info("SERVER_STATUS", "Server started at http://%s%s/" % (str(Config.address), port)) greenlet.join()
def __call__(self, environ, start_response): try: return self.wsgi_app(environ, start_response) except: Logger.error("UNCAUGHT_EXCEPTION", traceback.format_exc()) return InternalServerError()
def worker(task_name): """ Method that stays in the background and generates inputs """ task = ContestManager.tasks[task_name] queue = ContestManager.input_queue[task_name] while True: try: id = Database.gen_id() path = StorageManager.new_input_file(id, task_name, "invalid") seed = int(sha256(id.encode()).hexdigest(), 16) % (2**31) stdout = os.open( StorageManager.get_absolute_path(path), os.O_WRONLY | os.O_CREAT, 0o644, ) try: start_time = time.monotonic() # generate the input and store the stdout into a file retcode = gevent.subprocess.call( [task["generator"], str(seed), "0"], stdout=stdout) if time.monotonic() > start_time + 1: Logger.warning( "TASK", "Generation of input %s for task %s took %f seconds" % (seed, task_name, time.monotonic() - start_time), ) finally: os.close(stdout) if retcode != 0: Logger.error( "TASK", "Error %d generating input %s (%d) for task %s" % (retcode, id, seed, task_name), ) # skip the input continue # if there is a validator in the task use it to check if the # generated input is valid if "validator" in task: stdin = os.open(StorageManager.get_absolute_path(path), os.O_RDONLY) try: start_time = time.monotonic() # execute the validator piping the input file to stdin retcode = gevent.subprocess.call( [task["validator"], "0"], stdin=stdin) if time.monotonic() > start_time + 1: Logger.warning( "TASK", "Validation of input %s for task %s took %f " "seconds" % (seed, task_name, time.monotonic() - start_time), ) finally: os.close(stdin) if retcode != 0: Logger.error( "TASK", "Error %d validating input %s (%d) for task %s" % (retcode, id, seed, task_name), ) # skip the input continue Logger.debug( "TASK", "Generated input %s (%d) for task %s" % (id, seed, task_name), ) # this method is blocking if the queue is full queue.put({"id": id, "path": path}) except: Logger.error( "TASK", "Exception while creating an input file: " + traceback.format_exc(), )