swap-related units user input validation

This commit is contained in:
Alexey Avramov 2019-01-31 21:42:00 +09:00
parent 5cad925f5f
commit bd313a6952

176
nohang
View File

@ -40,27 +40,11 @@ HR = '~' * 79
print_total_stat = True
##########################################################################
# define functions
def zenity():
# test
os.system('''sudo -u user DISPLAY=:0 DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus zenity --checklist --timeout=10 --text="\n <b>Mem Available: 10% (300 MiB)</b>. \n\n Select a process to be terminated:\n" --ok-label "Terminate" --cancel-label "Do nothing" --separator=" " --width=9999 --height=9999 --list --title="Low memory!" --column "" --column="Pid" --column="Name" --column="VmRSS" 9923 9923 Python3 "800 MiB" 2938 2938 tail "400 MiB" 3938 3938 chromium "300 MiB"''')
# zenity()
def update_stat_dict_and_print(key):
if key not in stat_dict:
@ -83,7 +67,6 @@ def update_stat_dict_and_print(key):
print(stats_msg)
def psi_mem_some_avg_total():
if psi_support:
return float(rline1(psi_path).rpartition('=')[2])
@ -510,11 +493,6 @@ def find_victim_and_send_signal(signal):
if victim_badness >= min_badness:
# Try to send signal to found victim
# Get VmRSS and VmSwap and cmdline of victim process
@ -566,12 +544,14 @@ def find_victim_and_send_signal(signal):
except FileNotFoundError:
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')
update_stat_dict_and_print(
'The victim died in the search process: FileNotFoundError')
return None
except ProcessLookupError:
print(mem_info)
print('The victim died in the search process: ProcessLookupError')
update_stat_dict_and_print('The victim died in the search process: ProcessLookupError')
update_stat_dict_and_print(
'The victim died in the search process: ProcessLookupError')
return None
except UnicodeDecodeError:
@ -585,7 +565,8 @@ def find_victim_and_send_signal(signal):
uid = f_list[i].split('\t')[2]
if i is vm_size_index:
vm_size = kib_to_mib(int(f_list[i].split('\t')[1][:-3]))
vm_size = kib_to_mib(
int(f_list[i].split('\t')[1][:-3]))
if i is vm_rss_index:
vm_rss = kib_to_mib(int(f_list[i].split('\t')[1][:-3]))
@ -605,8 +586,8 @@ def find_victim_and_send_signal(signal):
int(f_list[i].split('\t')[1][:-3]))
if i is vm_swap_index:
vm_swap = kib_to_mib(int(f_list[i].split('\t')[1][:-3]))
vm_swap = kib_to_mib(
int(f_list[i].split('\t')[1][:-3]))
with open('/proc/' + pid + '/cmdline') as file:
cmdline = file.readlines()[0].replace('\x00', ' ')
@ -617,15 +598,16 @@ def find_victim_and_send_signal(signal):
except IndexError:
print(mem_info)
print('The victim died in the search process: IndexError')
update_stat_dict_and_print('The victim died in the search process: IndexError')
update_stat_dict_and_print(
'The victim died in the search process: IndexError')
return None
except ValueError:
print(mem_info)
print('The victim died in the search process: ValueError')
update_stat_dict_and_print('The victim died in the search process: ValueError')
update_stat_dict_and_print(
'The victim died in the search process: ValueError')
return None
len_vm = len(str(vm_size))
if detailed_rss:
@ -679,16 +661,6 @@ def find_victim_and_send_signal(signal):
str(vm_swap).rjust(len_vm),
cmdline)
if execute_the_command and signal is SIGTERM and name in etc_dict:
command = etc_dict[name]
exit_status = os.system(etc_dict[name].replace(
@ -719,22 +691,16 @@ def find_victim_and_send_signal(signal):
name,
command.replace('$PID', pid).replace('$NAME', pid_to_name(pid)))
else:
try:
t0 = time()
m = check_mem_and_swap()
ma = round(int(m[0]) / 1024.0)
sf = round(int(m[2]) / 1024.0)
print('\nMemory status before sending a signal:\nMemAv: {} MiB, SwFree: {} MiB'.format(ma, sf))
print(time() - t0)
print('\nMemory status before sending a signal:\nMemA'
'v: {} MiB, SwFree: {} MiB'.format(ma, sf))
os.kill(int(pid), signal)
response_time = time() - time0
send_result = '\033[32mOK\033[0m; response time: {} ms'.format(
@ -748,10 +714,6 @@ def find_victim_and_send_signal(signal):
key = 'Send \033[35m{}\033[0m to \033[35m{}\033[0m'.format(
sig_dict[signal], name)
# zenity()
if gui_notifications:
send_notify(signal, name, pid)
@ -766,15 +728,11 @@ def find_victim_and_send_signal(signal):
round(response_time * 1000))
key = 'The victim died in the search process: ProcessLookupError'
print(mem_info)
print(preventing_oom_message)
update_stat_dict_and_print(key)
else:
response_time = time() - time0
@ -791,11 +749,9 @@ def find_victim_and_send_signal(signal):
key = 'victim badness < min_badness'
update_stat_dict_and_print(key)
sleep_after_send_signal(signal)
def sleep_after_check_mem():
"""Specify sleep times depends on rates and avialable memory."""
@ -955,6 +911,8 @@ cd = os.getcwd()
config = '/etc/nohang/nohang.conf'
# config = 'nohang.conf'
print('Config:', config)
@ -1121,7 +1079,6 @@ else:
exit()
# НУЖНА ВАЛИДАЦИЯ НА МЕСТЕ!
if 'swap_min_sigterm' in config_dict:
swap_min_sigterm = config_dict['swap_min_sigterm']
else:
@ -1129,7 +1086,6 @@ else:
exit()
# НУЖНА ВАЛИДАЦИЯ НА МЕСТЕ!
if 'swap_min_sigkill' in config_dict:
swap_min_sigkill = config_dict['swap_min_sigkill']
else:
@ -1249,7 +1205,6 @@ else:
exit()
# НА МЕСТЕ!!!
if 'swap_min_warnings' in config_dict:
swap_min_warnings = config_dict['swap_min_warnings']
else:
@ -1260,50 +1215,72 @@ else:
##########################################################################
# Get Kibibytes levels
# Get KiB levels if it's possible.
# получ кб. если не кб - то процент. Если процент - находим кб ниже на
# основе полученного своптотал и процентов.
# Returns Kibibytes value if absolute value was set in config,
# or tuple with percentage
def sig_level_to_kb_swap(string):
"""Returns Kibibytes value if abs val was set in config, or tuple with %"""
def get_swap_threshold_tuple(string):
# re (Num %, True) or (Num KiB, False)
"""Returns KiB value if abs val was set in config, or tuple with %"""
# return tuple with abs and bool: (abs %, True) or (abs MiB, False)
if string.endswith('%'):
return float(string[:-1].strip()), True
valid = string_to_float_convert_test(string[:-1])
if valid is None:
print('somewhere swap unit is not float_%')
exit()
value = float(string[:-1].strip())
if value < 0 or value > 100:
print('invalid value, must be from the range[0; 100] %')
exit()
return value, True
elif string.endswith('M'):
return float(string[:-1].strip()) * 1024
valid = string_to_float_convert_test(string[:-1])
if valid is None:
print('somewhere swap unit is not float_M')
exit()
value = float(string[:-1].strip()) * 1024
if value < 0:
print('invalid unit in config (negative value)')
exit()
return value, False
else:
print('Invalid config file. There are invalid units somewhere\nExit')
exit()
# So, get them
swap_min_sigterm_swap = sig_level_to_kb_swap(swap_min_sigterm)
swap_min_sigkill_swap = sig_level_to_kb_swap(swap_min_sigkill)
swap_min_warnings_swap = sig_level_to_kb_swap(swap_min_warnings)
swap_min_sigterm_tuple = get_swap_threshold_tuple(swap_min_sigterm)
swap_min_sigkill_tuple = get_swap_threshold_tuple(swap_min_sigkill)
swap_min_warnings_tuple = get_swap_threshold_tuple(swap_min_warnings)
if isinstance(swap_min_sigterm_swap, tuple):
swap_term_is_percent = True
swap_min_sigterm_percent = swap_min_sigterm_swap[0]
swap_term_is_percent = swap_min_sigterm_tuple[1]
if swap_term_is_percent:
swap_min_sigterm_percent = swap_min_sigterm_tuple[0]
else:
swap_term_is_percent = False
swap_min_sigterm_kb = swap_min_sigterm_swap
swap_min_sigterm_kb = swap_min_sigterm_tuple[0]
if isinstance(swap_min_sigkill_swap, tuple):
swap_kill_is_percent = True
swap_min_sigkill_percent = swap_min_sigkill_swap[0]
swap_kill_is_percent = swap_min_sigkill_tuple[1]
if swap_kill_is_percent:
swap_min_sigkill_percent = swap_min_sigkill_tuple[0]
else:
swap_kill_is_percent = False
swap_min_sigkill_kb = swap_min_sigkill_swap
swap_min_sigkill_kb = swap_min_sigkill_tuple[0]
if isinstance(swap_min_warnings_swap, tuple):
swap_warn_is_percent = True
swap_min_warnings_percent = swap_min_warnings_swap[0]
swap_warn_is_percent = swap_min_warnings_tuple[1]
if swap_warn_is_percent:
swap_min_warnings_percent = swap_min_warnings_tuple[0]
else:
swap_warn_is_percent = False
swap_min_warnings_kb = swap_min_warnings_swap
swap_min_warnings_kb = swap_min_warnings_tuple[0]
##########################################################################
@ -1413,16 +1390,6 @@ if psi_support and not ignore_psi:
avg_value = ''
while True:
if psi_support and not ignore_psi:
@ -1447,6 +1414,8 @@ while True:
mem_available, swap_total, swap_free = check_mem_and_swap()
# если метры - получаем киб выше и сразу. см.
# if swap_min_sigkill is set in percent
if swap_kill_is_percent:
swap_min_sigkill_kb = swap_total * swap_min_sigkill_percent / 100.0
@ -1457,6 +1426,9 @@ while True:
if swap_warn_is_percent:
swap_min_warnings_kb = swap_total * swap_min_warnings_percent / 100.0
# в общем случае для работы нужны килобайты. Если в процентах задано -
# находим КБ тут, после получения своптотал.
mem_used_zram = check_zram()
if print_mem_check_results:
@ -1503,6 +1475,8 @@ while True:
# печатать так: SwapTotal = 0, ignore swapspace
swap_sigterm_pc = '-'
# это для печати меминфо. Все переработать нахрен.
# далее пошло ветвление
# MEM SWAP KILL
@ -1563,7 +1537,7 @@ while True:
percent(mem_available / mem_total),
kib_to_mib(mem_min_sigterm_kb),
# percent(mem_min_sigterm_kb / mem_total),
# ОКРУГЛЯТЬ НА МЕСТЕ ВЫШЕ
# ОКРУГЛЯТЬ НА МЕСТЕ ВЫШЕ (или не выше, хз)
round(mem_min_sigterm_percent, 1),
kib_to_mib(swap_free),
percent(swap_free / (swap_total + 0.1)),