improve victim search algorithm; add realpath and state to victim info

This commit is contained in:
Alexey Avramov 2019-02-08 03:23:13 +09:00
parent bf0ea46729
commit a8a0b43d3e
5 changed files with 7137 additions and 73 deletions

1754
n11 Executable file

File diff suppressed because it is too large Load Diff

1766
n4 Executable file

File diff suppressed because it is too large Load Diff

1779
n6 Executable file

File diff suppressed because it is too large Load Diff

148
nohang
View File

@ -44,21 +44,12 @@ stop_cont = False
stop_cont_warn = False stop_cont_warn = False
# print(os.path.realpath('/proc/29758/exe'))
########################################################################## ##########################################################################
# define functions # define functions
def pid_to_state(pid): def pid_to_state(pid):
return rline1('/proc/' + pid + '/stat').rpartition(')')[2][1] return rline1('/proc/' + pid + '/stat').rpartition(')')[2][1]
@ -110,12 +101,6 @@ def cont(stopped_list):
def update_stat_dict_and_print(key): def update_stat_dict_and_print(key):
if key not in stat_dict: if key not in stat_dict:
@ -356,29 +341,6 @@ def pid_to_cmdline(pid):
def pid_to_environ(pid):
"""
Get process cmdline by pid.
pid: str pid of required process
returns string cmdline
"""
with open('/proc/' + pid + '/environ') as f:
return f.read().replace('\x00', '\n').rstrip()
def pid_to_uid(pid): def pid_to_uid(pid):
'''return euid''' '''return euid'''
try: try:
@ -526,32 +488,64 @@ def sleep_after_send_signal(signal):
sleep(min_delay_after_sigterm) sleep(min_delay_after_sigterm)
def get_pid_list():
"""
Find pid list expect kthreads and zombies
"""
pid_list = []
for pid in os.listdir('/proc'):
if os.path.exists('/proc/' + pid + '/exe') is True:
pid_list.append(pid)
return pid_list
pid_list = get_pid_list()
def get_non_decimal_pids():
non_decimal_list = []
for pid in pid_list:
if pid[0].isdecimal() is False:
non_decimal_list.append(pid)
return non_decimal_list
#print(get_non_decimal_pids())
def fattest(): def fattest():
""" """
Find the process with highest badness and its badness adjustment Find the process with highest badness and its badness adjustment
Return pid and badness Return pid and badness
-> find_mem_hog() or find_victim() -> find_mem_hog() or find_victim() or find_worst_process()
""" """
pid_list = get_pid_list()
pid_list.remove(self_pid)
if '1' in pid_list:
pid_list.remove('1')
non_decimal_list = get_non_decimal_pids()
for i in non_decimal_list:
pid_list.remove(i)
pid_badness_list = [] pid_badness_list = []
for pid in os.listdir('/proc'): for pid in pid_list:
# only directories whose names consist only of numbers, except /proc/1/
if pid[0].isdecimal() is False or pid is '1' or pid == self_pid:
continue
# find and modify badness (if it needs) # find and modify badness (if it needs)
try: try:
#realpath = os.path.realpath('/proc/' + pid + '/exe')
#print(pid, pid_to_name(pid), realpath)
badness = int(rline1('/proc/' + pid + '/oom_score')) badness = int(rline1('/proc/' + pid + '/oom_score'))
if decrease_oom_score_adj: if decrease_oom_score_adj:
@ -586,6 +580,7 @@ def fattest():
continue continue
badness += int(re_tup[0]) badness += int(re_tup[0])
except FileNotFoundError: except FileNotFoundError:
continue continue
except ProcessLookupError: except ProcessLookupError:
@ -593,6 +588,7 @@ def fattest():
pid_badness_list.append((pid, badness)) pid_badness_list.append((pid, badness))
# Make list of (pid, badness) tuples, sorted by 'badness' values # Make list of (pid, badness) tuples, sorted by 'badness' values
#print(pid_badness_list)
pid_tuple_list = sorted( pid_tuple_list = sorted(
pid_badness_list, pid_badness_list,
key=itemgetter(1), key=itemgetter(1),
@ -604,9 +600,14 @@ def fattest():
# Get maximum 'badness' value # Get maximum 'badness' value
victim_badness = pid_tuple_list[1] victim_badness = pid_tuple_list[1]
#print(pid_badness_list)
return pid, victim_badness return pid, victim_badness
def find_victim_and_send_signal(signal): def find_victim_and_send_signal(signal):
""" """
Find victim with highest badness and send SIGTERM/SIGKILL Find victim with highest badness and send SIGTERM/SIGKILL
@ -619,7 +620,6 @@ def find_victim_and_send_signal(signal):
stopped_list = stop() stopped_list = stop()
pid, victim_badness = fattest() pid, victim_badness = fattest()
name = pid_to_name(pid) name = pid_to_name(pid)
@ -667,9 +667,7 @@ def find_victim_and_send_signal(signal):
vm_swap = kib_to_mib(int(line.split('\t')[1][:-4])) vm_swap = kib_to_mib(int(line.split('\t')[1][:-4]))
break break
with open('/proc/' + pid + '/cmdline') as file: cmdline = pid_to_cmdline(pid)
cmdline = file.readlines()[0].replace('\x00', ' ')
oom_score = rline1('/proc/' + pid + '/oom_score') oom_score = rline1('/proc/' + pid + '/oom_score')
oom_score_adj = rline1('/proc/' + pid + '/oom_score_adj') oom_score_adj = rline1('/proc/' + pid + '/oom_score_adj')
@ -750,26 +748,33 @@ def find_victim_and_send_signal(signal):
len_vm = len(str(vm_size)) len_vm = len(str(vm_size))
realpath = os.path.realpath('/proc/' + pid + '/exe')
state = pid_to_state(pid)
if detailed_rss: if detailed_rss:
environ = pid_to_environ(pid)
victim_info = '\033[4mFound a process with highest badness:\033[0m' \ victim_info = '\033[4mFound a process with highest badness:\033[0m' \
'\n Name: \033[33m{}\033[0m' \ '\n Name: \033[33m{}\033[0m' \
'\n PID: \033[33m{}\033[0m' \ '\n State: \033[33m{}\033[0m' \
'\n UID: \033[33m{}\033[0m' \ '\n PID: \033[33m{}\033[0m' \
'\n badness: \033[33m{}\033[0m, ' \ '\n UID: \033[33m{}\033[0m' \
'oom_score: \033[33m{}\033[0m, ' \ '\n badness: \033[33m{}\033[0m, ' \
'oom_score_adj: \033[33m{}\033[0m' \ 'oom_score: \033[33m{}\033[0m, ' \
'\n VmSize: \033[33m{}\033[0m MiB' \ 'oom_score_adj: \033[33m{}\033[0m' \
'\n VmRSS: \033[33m{}\033[0m MiB (' \ '\n VmSize: \033[33m{}\033[0m MiB' \
'\n VmRSS: \033[33m{}\033[0m MiB (' \
'Anon: \033[33m{}\033[0m MiB, ' \ 'Anon: \033[33m{}\033[0m MiB, ' \
'File: \033[33m{}\033[0m MiB, ' \ 'File: \033[33m{}\033[0m MiB, ' \
'Shmem: \033[33m{}\033[0m MiB)' \ 'Shmem: \033[33m{}\033[0m MiB)' \
'\n VmSwap: \033[33m{}\033[0m MiB' \ '\n VmSwap: \033[33m{}\033[0m MiB' \
'\n environ:\n\033[33m{}\033[0m' \ '\n realpath: \033[33m{}\033[0m' \
'\n cmdline: \033[33m{}\033[0m'.format( '\n cmdline: \033[33m{}\033[0m'.format(
name, name,
state,
pid, pid,
uid, uid,
victim_badness, victim_badness,
@ -781,7 +786,7 @@ def find_victim_and_send_signal(signal):
file_rss, file_rss,
shmem_rss, shmem_rss,
str(vm_swap).rjust(len_vm), str(vm_swap).rjust(len_vm),
environ, realpath,
cmdline cmdline
) )
else: else:
@ -846,8 +851,6 @@ def find_victim_and_send_signal(signal):
try: try:
m = check_mem_and_swap() m = check_mem_and_swap()
ma = round(int(m[0]) / 1024.0) ma = round(int(m[0]) / 1024.0)
sf = round(int(m[2]) / 1024.0) sf = round(int(m[2]) / 1024.0)
@ -855,7 +858,6 @@ def find_victim_and_send_signal(signal):
'v: {} MiB, SwFree: {} MiB'.format(ma, sf)) 'v: {} MiB, SwFree: {} MiB'.format(ma, sf))
if stop_cont: if stop_cont:
os.kill(int(pid), SIGCONT) os.kill(int(pid), SIGCONT)

1763
nohang2 Executable file

File diff suppressed because it is too large Load Diff