Skip to content
Open
Show file tree
Hide file tree
Changes from 6 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
2 changes: 1 addition & 1 deletion src/sinol_make/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from sinol_make.task_type.interactive import InteractiveTaskType # noqa


__version__ = "1.9.7"
__version__ = "1.9.8"


def configure_parsers():
Expand Down
12 changes: 6 additions & 6 deletions src/sinol_make/commands/chkwer/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def compile(self, file_path, exe_path, args, name, compilation_flags):
print(f'Compiling {name}... ', end='')
compilers = compiler.verify_compilers(args, [file_path])
exe, compile_log_path = compile.compile_file(file_path, exe_path, compilers, compilation_flags,
use_fsanitize=False, use_extras=False)
use_sanitizers=self.args.sanitize, use_extras=False)
if exe is None:
print(util.error('ERROR'))
compile.print_compile_log(compile_log_path)
Expand All @@ -57,11 +57,11 @@ def run_test(self, execution: ChkwerExecution) -> RunResult:
"""
output_file = paths.get_chkwer_path(os.path.basename(execution.out_test_path))
with open(execution.in_test_path, 'r') as inf, open(output_file, 'w') as outf:
process = subprocess.Popen([execution.model_exe], stdin=inf, stdout=outf)
process.wait()
process = subprocess.Popen([execution.model_exe], stdin=inf, stdout=outf, stderr=subprocess.PIPE)
_, stderr = process.communicate()
ok, points, comment = self.task_type.check_output(execution.in_test_path, output_file, execution.out_test_path)

return RunResult(execution.in_test_path, ok, int(points), comment)
return RunResult(execution.in_test_path, ok, int(points), comment, stderr.decode('utf-8'))

def run_and_print_table(self) -> Dict[str, TestResult]:
results = {}
Expand All @@ -84,7 +84,7 @@ def run_and_print_table(self) -> Dict[str, TestResult]:
try:
with mp.Pool(self.cpus) as pool:
for i, result in enumerate(pool.imap(self.run_test, executions)):
table_data.results[result.test_path].set_results(result.points, result.ok, result.comment)
table_data.results[result.test_path].set_results(result.points, result.ok, result.comment, result.stderr)
table_data.i = i
except KeyboardInterrupt:
keyboard_interrupt = True
Expand All @@ -99,7 +99,7 @@ def run_and_print_table(self) -> Dict[str, TestResult]:
return results

def run(self, args):
args = util.init_package_command(args)
self.args = util.init_package_command(args)
self.task_id = package_util.get_task_id()
self.task_type = package_util.get_task_type("time", None)
self.contest_type = contest_types.get_contest_type()
Expand Down
4 changes: 3 additions & 1 deletion src/sinol_make/commands/chkwer/chkwer_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,9 @@ def print_line_separator():

output = []
if result.run:
if result.comment:
if result.stderr != "":
print(util.error("stderr:"), result.stderr, end=' | ')
elif result.comment:
print(result.comment)
else:
print(util.color_gray("No comment"))
Expand Down
4 changes: 2 additions & 2 deletions src/sinol_make/commands/export/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ def generate_input_tests(self):
if ingen_exists(self.task_id):
ingen_path = get_ingen(self.task_id)
ingen_path = os.path.join(prog_dir, os.path.basename(ingen_path))
ingen_exe = compile_ingen(ingen_path, self.args, self.args.compile_mode)
ingen_exe = compile_ingen(ingen_path, self.args, self.args.compile_mode, use_sanitizers=self.args.sanitize)
if not run_ingen(ingen_exe, in_dir):
util.exit_with_error('Failed to run ingen.')

Expand All @@ -76,7 +76,7 @@ def generate_output_files(self):
if len(outputs) > 0:
outgen = OutgenCommand()
correct_solution_exe = compile_correct_solution(get_correct_solution(self.task_id), self.args,
self.args.compile_mode)
self.args.compile_mode, use_sanitizers=self.args.sanitize)
outgen.args = self.args
outgen.correct_solution_exe = correct_solution_exe
outgen.generate_outputs(outputs)
Expand Down
1 change: 0 additions & 1 deletion src/sinol_make/commands/gen/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ def configure_subparser(self, subparser):
parsers.add_cpus_argument(parser, 'number of cpus to use to generate output files')
parser.add_argument('-n', '--no-validate', default=False, action='store_true',
help='do not validate test contents')
parsers.add_fsanitize_argument(parser)
parsers.add_compilation_arguments(parser)
return parser

Expand Down
4 changes: 2 additions & 2 deletions src/sinol_make/commands/ingen/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ def configure_subparser(self, subparser):
parser.add_argument('-n', '--no-validate', default=False, action='store_true',
help='do not validate test contents')
parsers.add_cpus_argument(parser, 'number of cpus used for validating tests')
parsers.add_fsanitize_argument(parser)
parsers.add_compilation_arguments(parser)
return parser

Expand Down Expand Up @@ -67,7 +66,8 @@ def run(self, args: argparse.Namespace):
util.change_stack_size_to_unlimited()
self.ingen = get_ingen(self.task_id, args.ingen_path)
print(f'Using ingen file {os.path.basename(self.ingen)}')
self.ingen_exe = compile_ingen(self.ingen, self.args, self.args.compile_mode, self.args.fsanitize)
self.ingen_exe = compile_ingen(self.ingen, self.args, self.args.compile_mode,
use_sanitizers=self.args.sanitize)

previous_tests = []
try:
Expand Down
11 changes: 8 additions & 3 deletions src/sinol_make/commands/ingen/ingen_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def get_ingen(task_id, ingen_path=None):
return correct_ingen


def compile_ingen(ingen_path: str, args: argparse.Namespace, compilation_flags='default', use_fsanitize=False):
def compile_ingen(ingen_path: str, args: argparse.Namespace, compilation_flags='default', use_sanitizers='no'):
"""
Compiles ingen and returns path to compiled executable.
If ingen_path is shell script, then it will be returned.
Expand All @@ -57,7 +57,7 @@ def compile_ingen(ingen_path: str, args: argparse.Namespace, compilation_flags='

compilers = compiler.verify_compilers(args, [ingen_path])
ingen_exe, compile_log_path = compile.compile_file(ingen_path, package_util.get_executable(ingen_path),
compilers, compilation_flags, use_fsanitize=use_fsanitize,
compilers, compilation_flags, use_sanitizers=use_sanitizers,
additional_flags='-D_INGEN', use_extras=False)

if ingen_exe is None:
Expand All @@ -84,7 +84,7 @@ def run_ingen(ingen_exe, working_dir=None):
os.chmod(ingen_exe, st.st_mode | stat.S_IEXEC)

print(util.bold(' Ingen output '.center(util.get_terminal_size()[1], '=')))
process = subprocess.Popen([ingen_exe], stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
process = subprocess.Popen([ingen_exe], stdout=subprocess.PIPE, stderr=subprocess.PIPE,
cwd=working_dir, shell=is_shell)
whole_output = ''
while process.poll() is None:
Expand All @@ -98,6 +98,11 @@ def run_ingen(ingen_exe, working_dir=None):
exit_code = process.returncode
print(util.bold(' End of ingen output '.center(util.get_terminal_size()[1], '=')))

stderr = process.stderr.read()
if stderr:
print(util.error('Ingen error output:'))
print(stderr.decode('utf-8'), end='\n\n')

if util.has_sanitizer_error(whole_output, exit_code):
print(util.warning('Warning: if ingen failed due to sanitizer errors, you can either run '
'`sudo sysctl vm.mmap_rnd_bits=28` to fix this or disable sanitizers with the '
Expand Down
4 changes: 2 additions & 2 deletions src/sinol_make/commands/inwer/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ def configure_subparser(self, subparser: argparse.ArgumentParser):
parser.add_argument('-t', '--tests', type=str, nargs='+',
help='test to verify, for example in/abc{0,1}*')
parsers.add_cpus_argument(parser, 'number of cpus to use when verifying tests')
parsers.add_fsanitize_argument(parser)
parsers.add_compilation_arguments(parser)
return parser

Expand Down Expand Up @@ -204,7 +203,8 @@ def run(self, args: argparse.Namespace):
print('Verifying tests: ' + util.bold(', '.join(self.tests)))

util.change_stack_size_to_unlimited()
self.inwer_executable = inwer_util.compile_inwer(self.inwer, args, args.compile_mode, args.fsanitize)
self.inwer_executable = inwer_util.compile_inwer(self.inwer, args, args.compile_mode,
use_sanitizers=args.sanitize)
results: Dict[str, TestResult] = self.verify_and_print_table()
print('')

Expand Down
4 changes: 2 additions & 2 deletions src/sinol_make/commands/inwer/inwer_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,13 @@ def get_inwer_path(task_id: str, path=None) -> Union[str, None]:
return None


def compile_inwer(inwer_path: str, args: argparse.Namespace, compilation_flags='default', use_fsanitize=False):
def compile_inwer(inwer_path: str, args: argparse.Namespace, compilation_flags='default', use_sanitizers='no'):
"""
Compiles inwer and returns path to compiled executable and path to compile log.
"""
compilers = compiler.verify_compilers(args, [inwer_path])
inwer_exe, compile_log_path = compile.compile_file(inwer_path, package_util.get_executable(inwer_path), compilers,
compilation_flags, use_fsanitize=use_fsanitize,
compilation_flags, use_sanitizers=use_sanitizers,
additional_flags='-D_INWER', use_extras=False)

if inwer_exe is None:
Expand Down
13 changes: 9 additions & 4 deletions src/sinol_make/commands/outgen/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,16 @@ def generate_outputs(self, outputs_to_generate):

with mp.Pool(self.args.cpus) as pool:
results = []
for i, result in enumerate(pool.imap(generate_output, arguments)):
for i, (result, stderr) in enumerate(pool.imap(generate_output, arguments)):
results.append(result)
output_file = os.path.basename(arguments[i].output_test)
if stderr:
print(util.error(f'Outgen stderr on {output_file}:'))
print(stderr.decode('utf-8'), end='\n\n')
if result:
print(f'Successfully generated output file {os.path.basename(arguments[i].output_test)}')
print(f'Successfully generated output file {output_file}')
else:
print(util.error(f'Failed to generate output file {os.path.basename(arguments[i].output_test)}'))
print(util.error(f'Failed to generate output file {output_file}'))

if not all(results):
util.exit_with_error('Failed to generate some output files.')
Expand Down Expand Up @@ -123,7 +127,8 @@ def run(self, args: argparse.Namespace):
else:
self.clean_cache(from_inputs)
self.correct_solution_exe = compile_correct_solution(self.correct_solution, self.args,
self.args.compile_mode)
self.args.compile_mode,
use_sanitizers=self.args.sanitize)
self.generate_outputs(outputs_to_generate)
with open(os.path.join(os.getcwd(), 'in', '.md5sums'), 'w') as f:
yaml.dump(md5_sums, f)
Expand Down
10 changes: 5 additions & 5 deletions src/sinol_make/commands/outgen/outgen_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@ def get_correct_solution(task_id):
return correct_solution[0]


def compile_correct_solution(solution_path: str, args: argparse.Namespace, compilation_flags='default'):
def compile_correct_solution(solution_path: str, args: argparse.Namespace, compilation_flags='default', use_sanitizers='no'):
"""
Compiles correct solution and returns path to compiled executable.
"""
compilers = compiler.verify_compilers(args, [solution_path])
correct_solution_exe, compile_log_path = compile.compile_file(solution_path, package_util.get_executable(solution_path), compilers,
compilation_flags)
compilation_flags, use_sanitizers=use_sanitizers)
if correct_solution_exe is None:
util.exit_with_error('Failed compilation of correct solution.',
lambda: compile.print_compile_log(compile_log_path))
Expand All @@ -49,7 +49,7 @@ def generate_output(arguments):

input_file = open(input_test, 'r')
output_file = open(output_test, 'w')
process = subprocess.Popen([correct_solution_exe], stdin=input_file, stdout=output_file, preexec_fn=os.setsid)
process = subprocess.Popen([correct_solution_exe], stdin=input_file, stdout=output_file, stderr=subprocess.PIPE, preexec_fn=os.setsid)
previous_sigint_handler = signal.getsignal(signal.SIGINT)

def sigint_handler(signum, frame):
Expand All @@ -60,10 +60,10 @@ def sigint_handler(signum, frame):
sys.exit(1)
signal.signal(signal.SIGINT, sigint_handler)

process.wait()
_, stderr = process.communicate()
signal.signal(signal.SIGINT, previous_sigint_handler)
exit_code = process.returncode
input_file.close()
output_file.close()

return exit_code == 0
return exit_code == 0, stderr
7 changes: 5 additions & 2 deletions src/sinol_make/commands/run/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,9 @@ def configure_subparser(self, subparser):
help='allow running the script without full outputs')
parser.add_argument('-o', '--comments', dest='comments', action='store_true',
help="show checker's comments")
parsers.add_compilation_arguments(parser)
parsers.add_compilation_arguments(parser, custom_sanitize_help='When using sanitizers, make sure '
'that you are running with `time` tool for measuring time and memory. '
'Sio2jail does not support sanitizers.')
return parser

def extract_file_name(self, file_path):
Expand Down Expand Up @@ -365,7 +367,8 @@ def compile(self, solution, dest=None, use_extras=False, clear_cache=False, name
try:
with open(compile_log_file, "w") as compile_log:
compile.compile(source_file, output, self.compilers, compile_log, self.args.compile_mode,
extra_compilation_args, extra_compilation_files, clear_cache=clear_cache)
extra_compilation_args, extra_compilation_files, clear_cache=clear_cache,
use_sanitizers=self.args.sanitize)
print(util.info(f"Compilation of {name} was successful."))
return True
except CompilationError as e:
Expand Down
2 changes: 1 addition & 1 deletion src/sinol_make/helpers/cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def get_cache_file(solution_path: str) -> CacheFile:
return CacheFile()


def check_compiled(file_path: str, compilation_flags: str, sanitizers: bool) -> Union[str, None]:
def check_compiled(file_path: str, compilation_flags: str, sanitizers: str) -> Union[str, None]:
"""
Check if a file is compiled
:param file_path: Path to the file
Expand Down
Loading
Loading