From 881cc7d20f2c3aa9a8dcbaa8114d8b486a3376a0 Mon Sep 17 00:00:00 2001 From: Alexey Avramov Date: Tue, 7 Aug 2018 15:03:01 +0900 Subject: [PATCH] improve GUI notifications --- nohang | 121 +++++++++++++++++++++++++++++++-------------------------- 1 file changed, 66 insertions(+), 55 deletions(-) diff --git a/nohang b/nohang index fb6dfb4..38e4f5a 100755 --- a/nohang +++ b/nohang @@ -234,10 +234,28 @@ def send_notify_warn(): Popen(['notify-send', '--icon=dialog-warning', '{}'.format(title), '{}'.format(body)]) -def send_notify(signal, name, pid, oom_score, vm_rss, vm_swap): +def send_notify(signal, name, pid): title = 'NOHANG TRIGGERED' body = '{} process {}, {}'.format( - notify_sig_dict[signal], pid, name) + notify_sig_dict[signal], pid, name.replace('&', '*')) + if root: + # отправляем уведомление всем залогиненным пользователям + b = root_notify_env() + if len(b) > 0: + for i in b: + username, display_env, dbus_env = i[0], i[1], i[2] + Popen(['sudo', '-u', username, 'env', display_env, + dbus_env, 'notify-send', '--icon=dialog-warning', + '{}'.format(title), '{}'.format(body)]) + else: + # отправляем уведомление пользователю, который запустил nohang + Popen(['notify-send', '--icon=dialog-warning', '{}'.format(title), '{}'.format(body)]) + + +def send_notify_etc(pid, name, command): + title = 'NOHANG TRIGGERED' + body = 'Victim is process {}, {}\nExecute the command:\n{}'.format( + pid, name.replace('&', '*'), command.replace('&', '*')) if root: # отправляем уведомление всем залогиненным пользователям b = root_notify_env() @@ -265,63 +283,55 @@ def sleep_after_send_signal(signal): def find_victim_and_send_signal(signal): - print(mem_info) - - # выставляем потолок для oom_score_adj всех процессов if decrease_oom_score_adj and root: func_decrease_oom_score_adj(oom_score_adj_max) - # получаем список процессов ((pid, badness)) - oom_list = [] + pid_badness_list = [] if regex_matching: for pid in os.listdir('/proc'): - if pid.isdigit() is not True: + if pid[0].isdecimal() is not True: continue + try: - # пошла итерация для каждого существующего процесса - oom_score = int(rline1('/proc/' + pid + '/oom_score')) + badness = int(rline1('/proc/' + pid + '/oom_score')) name = pid_to_name(pid) - res = fullmatch(avoid_regex, name) - if res is not None: - # тут уже получаем badness - oom_score = int(oom_score / avoid_factor) - print(' {} (Pid: {}, Badness {}) matches with avoid_regex'.format(name, pid, oom_score)), + if fullmatch(avoid_regex, name) is not None: + badness = int(badness / avoid_factor) - res = fullmatch(prefer_regex, name) - if res is not None: - oom_score = int((oom_score + 1) * prefer_factor) - print(' {} (Pid: {}, Badness {}) matches with prefer_regex'.format(name, pid, oom_score)), + if fullmatch(prefer_regex, name) is not None: + badness = int((badness + 1) * prefer_factor) except FileNotFoundError: - oom_score = 0 + badness = 0 except ProcessLookupError: - oom_score = 0 - oom_list.append((pid, oom_score)) + badness = 0 + pid_badness_list.append((pid, badness)) else: - # not use regex - for i in os.listdir('/proc'): - if i[0].isdecimal() is not True: + for pid in os.listdir('/proc'): + if pid[0].isdecimal() is not True: continue try: - oom_score = int(rline1('/proc/' + i + '/oom_score')) + badness = int(rline1('/proc/' + pid + '/oom_score')) except FileNotFoundError: - oom_score = 0 + badness = 0 except ProcessLookupError: - oom_score = 0 - oom_list.append((i, oom_score)) + badness = 0 + pid_badness_list.append((pid, badness)) - # получаем отсортированный по oom_score (по badness!) список пар (pid, oom_score) - pid_tuple_list = sorted(oom_list, key=itemgetter(1), reverse=True)[0] - # получаем максимальный oom_score - oom_score = pid_tuple_list[1] + # получаем отсортированный по badness список пар (pid, badness) + pid_tuple_list = sorted( + pid_badness_list, key=itemgetter(1), reverse=True)[0] - if oom_score >= min_badness: + # получаем максимальный badness + victim_badness = pid_tuple_list[1] + + if victim_badness >= min_badness: # пытаемся отправить сигнал найденной жертве @@ -356,43 +366,41 @@ def find_victim_and_send_signal(signal): if name in etc_dict and signal is signal.SIGTERM: command = etc_dict[name] - etc_info = ' Process {} is a victim,\n Pid: {}, Badness: {}, VmRSS: {} MiB, VmSwap: {} MiB\n Execute command: {}'.format(name, pid, oom_score, vm_rss, vm_swap, command) - os.system(etc_dict[name]) # все норм, это произвольная команда задана юзером + exit_status = os.system(etc_dict[name]) + response_time = time() - time0 + etc_info = ' Finding the process with the highest badness\n Victim is {}, pid: {}, badness: {}, VmRSS: {} MiB, VmSwap: {} MiB\n Execute the command: {}\n Exit status: {}; response time: {} ms'.format(name, pid, badness, vm_rss, vm_swap, command, exit_status, round(response_time * 1000)) + print(mem_info) print(etc_info) - # еще ГУИ уведомление запустить + if gui_notifications: + send_notify_etc(pid, name, command) else: - try: # delta_sucess -> response_time + try: os.kill(int(pid), signal) - delta_success = time() - time0 - send_result = 'signal received; response time: {} ms'.format(round(delta_success * 1000)) + response_time = time() - time0 + send_result = 'signal received; response time: {} ms'.format(round(response_time * 1000)) if gui_notifications: - send_notify(signal, name, pid, oom_score, vm_rss, vm_swap) + send_notify(signal, name, pid) except FileNotFoundError: - delta_success = time() - time0 - send_result = 'no such process; response time: {} ms'.format(round(delta_success * 1000)) + response_time = time() - time0 + send_result = 'no such process; response time: {} ms'.format(round(response_time * 1000)) except ProcessLookupError: - delta_success = time() - time0 - send_result = 'no such process; response time: {} ms'.format(round(delta_success * 1000)) - - preventing_oom_message = ' Finding the process with the highest badness\n Victim is {}, pid: {}, badness: {}, VmRSS: {} MiB, VmSwap: {} MiB\n Sending {} to the victim; {}'.format(name, pid, oom_score, vm_rss, vm_swap, sig_dict[signal], send_result) + response_time = time() - time0 + send_result = 'no such process; response time: {} ms'.format(round(response_time * 1000)) + preventing_oom_message = ' Finding the process with the highest badness\n Victim is {}, pid: {}, badness: {}, VmRSS: {} MiB, VmSwap: {} MiB\n Sending {} to the victim; {}'.format(name, pid, badness, vm_rss, vm_swap, sig_dict[signal], send_result) + print(mem_info) print(preventing_oom_message) else: - success_time = time() - delta_success = success_time - time0 - - # delta_success -> response_time - - badness_is_too_small = ' oom_score {} < min_badness {}; response time: {} ms'.format( - oom_score, min_badness, round(delta_success * 1000)) + response_time = time() - time0 + victim_badness_is_too_small = ' victim badness {} < min_badness {}; nothing to do; response time: {} ms'.format(victim_badness, min_badness, round(response_time * 1000)) - print(badness_is_too_small) + print(victim_badness_is_too_small) stdout.flush() @@ -1462,6 +1470,9 @@ while True: # SLEEP BETWEEN MEM CHECKS else: + stdout.flush() + sleep_after_check_mem() +