diff --git a/nohang b/nohang index 0918fde..0eae07a 100755 --- a/nohang +++ b/nohang @@ -29,21 +29,21 @@ if len(argv) == 1: elif len(argv) == 2: if argv[1] == '--help' or argv[1] == '-h': - print(help_mess) + errprint(help_mess) exit(1) else: - print('Invalid CLI input') + errprint('Invalid CLI input') exit(1) elif len(argv) > 3: - print('Invalid CLI input') + errprint('Invalid CLI input') exit(1) else: if argv[1] == '--config' or argv[1] == '-c': config = argv[2] else: - print('Invalid option: {}'.format(argv[1])) + errprint('Invalid option: {}'.format(argv[1])) exit(1) @@ -89,6 +89,10 @@ debug = False # define functions +def errprint(text): + print(text, file=stderr, flush=True) + + def mlockall(): MCL_CURRENT = 1 @@ -236,8 +240,8 @@ def conf_parse_string(param): if param in config_dict: return config_dict[param].strip() else: - print('All the necessary parameters must be in the config') - print('There is no "{}" parameter in the config'.format(param)) + errprint('All the necessary parameters must be in the config') + errprint('There is no "{}" parameter in the config'.format(param)) exit(1) @@ -255,13 +259,13 @@ def conf_parse_bool(param): elif param_str == 'False': return False else: - print('Invalid value of the "{}" parameter.'.format(param)) - print('Valid values are True and False.') - print('Exit') + errprint('Invalid value of the "{}" parameter.'.format(param)) + errprint('Valid values are True and False.') + errprint('Exit') exit(1) else: - print('All the necessary parameters must be in the config') - print('There is no "{}" parameter in the config'.format(param)) + errprint('All the necessary parameters must be in the config') + errprint('There is no "{}" parameter in the config'.format(param)) exit(1) @@ -795,7 +799,11 @@ def find_victim_and_send_signal(signal): try: realpath = os.path.realpath('/proc/' + pid + '/exe') except FileNotFoundError: - print('Victim died: /proc/{}/exe does not exists'.format(pid)) + print(mem_info) + print('The victim died in the search process: FileNotFoundError') + update_stat_dict_and_print( + 'The victim died in the search process: FileNotFoundError') + return None #state = pid_to_state(pid) @@ -982,7 +990,7 @@ def sleep_after_check_mem(): t_mem = mem_point / rate_mem t_swap = swap_point / rate_swap - t_zram = (mem_total * 0.9 - mem_used_zram) / rate_zram + t_zram = (mem_total * 0.8 - mem_used_zram) / rate_zram if t_zram < 0: t_zram = 0 @@ -1039,11 +1047,11 @@ def calculate_percent(arg_key): # then 'float test' mem_min_percent = string_to_float_convert_test(mem_min_percent) if mem_min_percent is None: - print('Invalid {} value, not float\nExit'.format(arg_key)) + errprint('Invalid {} value, not float\nExit'.format(arg_key)) exit(1) # Final validations... if mem_min_percent < 0 or mem_min_percent > 100: - print( + errprint( '{}, as percents value, out of range [0; 100]\nExit'.format(arg_key)) exit(1) @@ -1055,11 +1063,11 @@ def calculate_percent(arg_key): elif mem_min.endswith('M'): mem_min_mb = string_to_float_convert_test(mem_min[:-1].strip()) if mem_min_mb is None: - print('Invalid {} value, not float\nExit'.format(arg_key)) + errprint('Invalid {} value, not float\nExit'.format(arg_key)) exit(1) mem_min_kb = mem_min_mb * 1024 if mem_min_kb > mem_total: - print( + errprint( '{} value can not be greater then MemTotal ({} MiB)\nExit'.format( arg_key, round( mem_total / 1024))) @@ -1099,7 +1107,7 @@ for s in mem_list: mem_list_names.append(s.split(':')[0]) if mem_list_names[2] != 'MemAvailable': - print('Your Linux kernel is too old, Linux 3.14+ requied\nExit') + errprint('Your Linux kernel is too old, Linux 3.14+ requied\nExit') exit(1) swap_total_index = mem_list_names.index('SwapTotal') @@ -1183,7 +1191,7 @@ try: etc_name = a[0].strip() etc_command = a[1].strip() if len(etc_name) > 15: - print('Invalid config, the length of the process ' + errprint('Invalid config, the length of the process ' 'name must not exceed 15 characters\nExit') exit(1) etc_dict[etc_name] = etc_command @@ -1204,19 +1212,19 @@ try: uid_re_list.append((a[0].strip(' '), a[2].strip(' '))) except PermissionError: - print('PermissionError', conf_err_mess) + errprint('PermissionError', conf_err_mess) exit(1) except UnicodeDecodeError: - print('UnicodeDecodeError', conf_err_mess) + errprint('UnicodeDecodeError', conf_err_mess) exit(1) except IsADirectoryError: - print('IsADirectoryError', conf_err_mess) + errprint('IsADirectoryError', conf_err_mess) exit(1) except IndexError: - print('IndexError', conf_err_mess) + errprint('IndexError', conf_err_mess) exit(1) except FileNotFoundError: - print('FileNotFoundError', conf_err_mess) + errprint('FileNotFoundError', conf_err_mess) exit(1) @@ -1272,53 +1280,53 @@ zram_max_warnings_kb, zram_max_warnings_mb, zram_max_warnings_percent = calculat if 'rate_mem' in config_dict: rate_mem = string_to_float_convert_test(config_dict['rate_mem']) if rate_mem is None: - print('Invalid rate_mem value, not float\nExit') + errprint('Invalid rate_mem value, not float\nExit') exit(1) if rate_mem <= 0: - print('rate_mem MUST be > 0\nExit') + errprint('rate_mem MUST be > 0\nExit') exit(1) else: - print('rate_mem not in config\nExit') + errprint('rate_mem not in config\nExit') exit(1) if 'rate_swap' in config_dict: rate_swap = string_to_float_convert_test(config_dict['rate_swap']) if rate_swap is None: - print('Invalid rate_swap value, not float\nExit') + errprint('Invalid rate_swap value, not float\nExit') exit(1) if rate_swap <= 0: - print('rate_swap MUST be > 0\nExit') + errprint('rate_swap MUST be > 0\nExit') exit(1) else: - print('rate_swap not in config\nExit') + errprint('rate_swap not in config\nExit') exit(1) if 'rate_zram' in config_dict: rate_zram = string_to_float_convert_test(config_dict['rate_zram']) if rate_zram is None: - print('Invalid rate_zram value, not float\nExit') + errprint('Invalid rate_zram value, not float\nExit') exit(1) if rate_zram <= 0: - print('rate_zram MUST be > 0\nExit') + errprint('rate_zram MUST be > 0\nExit') exit(1) else: - print('rate_zram not in config\nExit') + errprint('rate_zram not in config\nExit') exit(1) if 'swap_min_sigterm' in config_dict: swap_min_sigterm = config_dict['swap_min_sigterm'] else: - print('swap_min_sigterm not in config\nExit') + errprint('swap_min_sigterm not in config\nExit') exit(1) if 'swap_min_sigkill' in config_dict: swap_min_sigkill = config_dict['swap_min_sigkill'] else: - print('swap_min_sigkill not in config\nExit') + errprint('swap_min_sigkill not in config\nExit') exit(1) @@ -1326,13 +1334,13 @@ if 'min_delay_after_sigterm' in config_dict: min_delay_after_sigterm = string_to_float_convert_test( config_dict['min_delay_after_sigterm']) if min_delay_after_sigterm is None: - print('Invalid min_delay_after_sigterm value, not float\nExit') + errprint('Invalid min_delay_after_sigterm value, not float\nExit') exit(1) if min_delay_after_sigterm < 0: - print('min_delay_after_sigterm must be positiv\nExit') + errprint('min_delay_after_sigterm must be positiv\nExit') exit(1) else: - print('min_delay_after_sigterm not in config\nExit') + errprint('min_delay_after_sigterm not in config\nExit') exit(1) @@ -1340,13 +1348,13 @@ if 'min_delay_after_sigkill' in config_dict: min_delay_after_sigkill = string_to_float_convert_test( config_dict['min_delay_after_sigkill']) if min_delay_after_sigkill is None: - print('Invalid min_delay_after_sigkill value, not float\nExit') + errprint('Invalid min_delay_after_sigkill value, not float\nExit') exit(1) if min_delay_after_sigkill < 0: - print('min_delay_after_sigkill must be positive\nExit') + errprint('min_delay_after_sigkill must be positive\nExit') exit(1) else: - print('min_delay_after_sigkill not in config\nExit') + errprint('min_delay_after_sigkill not in config\nExit') exit(1) @@ -1354,13 +1362,13 @@ if 'psi_avg10_sleep_time' in config_dict: psi_avg10_sleep_time = string_to_float_convert_test( config_dict['psi_avg10_sleep_time']) if psi_avg10_sleep_time is None: - print('Invalid psi_avg10_sleep_time value, not float\nExit') + errprint('Invalid psi_avg10_sleep_time value, not float\nExit') exit(1) if psi_avg10_sleep_time < 0: - print('psi_avg10_sleep_time must be positive\nExit') + errprint('psi_avg10_sleep_time must be positive\nExit') exit(1) else: - print('psi_avg10_sleep_time not in config\nExit') + errprint('psi_avg10_sleep_time not in config\nExit') exit(1) @@ -1368,13 +1376,13 @@ if 'sigkill_psi_avg10' in config_dict: sigkill_psi_avg10 = string_to_float_convert_test( config_dict['sigkill_psi_avg10']) if sigkill_psi_avg10 is None: - print('Invalid sigkill_psi_avg10 value, not float\nExit') + errprint('Invalid sigkill_psi_avg10 value, not float\nExit') exit(1) if sigkill_psi_avg10 < 0 or sigkill_psi_avg10 > 100: - print('sigkill_psi_avg10 must be in the range [0; 100]\nExit') + errprint('sigkill_psi_avg10 must be in the range [0; 100]\nExit') exit(1) else: - print('sigkill_psi_avg10 not in config\nExit') + errprint('sigkill_psi_avg10 not in config\nExit') exit(1) @@ -1382,13 +1390,13 @@ if 'sigterm_psi_avg10' in config_dict: sigterm_psi_avg10 = string_to_float_convert_test( config_dict['sigterm_psi_avg10']) if sigterm_psi_avg10 is None: - print('Invalid sigterm_psi_avg10 value, not float\nExit') + errprint('Invalid sigterm_psi_avg10 value, not float\nExit') exit(1) if sigterm_psi_avg10 < 0 or sigterm_psi_avg10 > 100: - print('sigterm_psi_avg10 must be in the range [0; 100]\nExit') + errprint('sigterm_psi_avg10 must be in the range [0; 100]\nExit') exit(1) else: - print('sigterm_psi_avg10 not in config\nExit') + errprint('sigterm_psi_avg10 not in config\nExit') exit(1) @@ -1396,13 +1404,13 @@ if 'min_badness' in config_dict: min_badness = string_to_int_convert_test( config_dict['min_badness']) if min_badness is None: - print('Invalid min_badness value, not integer\nExit') + errprint('Invalid min_badness value, not integer\nExit') exit(1) if min_badness < 0 or min_badness > 1000: - print('Invalud min_badness value\nExit') + errprint('Invalud min_badness value\nExit') exit(1) else: - print('min_badness not in config\nExit') + errprint('min_badness not in config\nExit') exit(1) @@ -1410,13 +1418,13 @@ if 'oom_score_adj_max' in config_dict: oom_score_adj_max = string_to_int_convert_test( config_dict['oom_score_adj_max']) if oom_score_adj_max is None: - print('Invalid oom_score_adj_max value, not integer\nExit') + errprint('Invalid oom_score_adj_max value, not integer\nExit') exit(1) if oom_score_adj_max < 0 or oom_score_adj_max > 1000: - print('Invalid oom_score_adj_max value\nExit') + errprint('Invalid oom_score_adj_max value\nExit') exit(1) else: - print('oom_score_adj_max not in config\nExit') + errprint('oom_score_adj_max not in config\nExit') exit(1) @@ -1424,20 +1432,20 @@ if 'min_time_between_warnings' in config_dict: min_time_between_warnings = string_to_float_convert_test( config_dict['min_time_between_warnings']) if min_time_between_warnings is None: - print('Invalid min_time_between_warnings value, not float\nExit') + errprint('Invalid min_time_between_warnings value, not float\nExit') exit(1) if min_time_between_warnings < 1 or min_time_between_warnings > 300: - print('min_time_between_warnings value out of range [1; 300]\nExit') + errprint('min_time_between_warnings value out of range [1; 300]\nExit') exit(1) else: - print('min_time_between_warnings not in config\nExit') + errprint('min_time_between_warnings not in config\nExit') exit(1) if 'swap_min_warnings' in config_dict: swap_min_warnings = config_dict['swap_min_warnings'] else: - print('swap_min_warnings not in config\nExit') + errprint('swap_min_warnings not in config\nExit') exit(1) @@ -1458,12 +1466,12 @@ def get_swap_threshold_tuple(string): if string.endswith('%'): valid = string_to_float_convert_test(string[:-1]) if valid is None: - print('somewhere swap unit is not float_%') + errprint('somewhere swap unit is not float_%') exit(1) value = float(string[:-1].strip()) if value < 0 or value > 100: - print('invalid value, must be from the range[0; 100] %') + errprint('invalid value, must be from the range[0; 100] %') exit(1) return value, True @@ -1471,18 +1479,18 @@ def get_swap_threshold_tuple(string): elif string.endswith('M'): valid = string_to_float_convert_test(string[:-1]) if valid is None: - print('somewhere swap unit is not float_M') + errprint('somewhere swap unit is not float_M') exit(1) value = float(string[:-1].strip()) * 1024 if value < 0: - print('invalid unit in config (negative value)') + errprint('invalid unit in config (negative value)') exit(1) return value, False else: - print('Invalid config file. There are invalid units somewhere\nExit') + errprint('Invalid config file. There are invalid units somewhere\nExit') exit(1) diff --git a/nohang.conf b/nohang.conf index 37e417b..bcbd6a7 100644 --- a/nohang.conf +++ b/nohang.conf @@ -95,7 +95,7 @@ psi_avg10_sleep_time = 60 rate_mem = 3 rate_swap = 1.5 -rate_zram = 1 +rate_zram = 0.5 See also https://github.com/rfjakob/earlyoom/issues/61