diff --git a/nohang b/nohang
index d1920ef..745e423 100755
--- a/nohang
+++ b/nohang
@@ -19,7 +19,7 @@ if self_uid == 0:
else:
root = False
-wait_time = 14
+wait_time = 12
max_sleep_time = 2
min_sleep_time = 0.1
@@ -29,6 +29,8 @@ notify_helper_path = '/usr/sbin/nohang_notify_helper'
psi_path = '/proc/pressure/memory'
psi_support = os.path.exists(psi_path)
+HR = '~' * 70
+
##########################################################################
@@ -182,11 +184,12 @@ def rline1(path):
for line in f:
return line[:-1]
-
+'''
def write(path, string):
"""Write string to path."""
with open(path, 'w') as f:
f.write(string)
+'''
def kib_to_mib(num):
@@ -247,12 +250,18 @@ def pid_to_name(pid):
"""
try:
with open('/proc/' + pid + '/status') as f:
+ f.seek(6)
for line in f:
- return line[:-1].split('\t')[1]
+ return line[:-1]
except FileNotFoundError:
return ''
except ProcessLookupError:
return ''
+ except UnicodeDecodeError:
+ with open('/proc/' + pid + '/status', 'rb') as f:
+ f.seek(6)
+ return f.read(15).decode(
+ 'utf-8', 'ignore').partition('\n')[0]
def pid_to_cmdline(pid):
@@ -262,22 +271,25 @@ def pid_to_cmdline(pid):
pid: str pid of required process
returns string cmdline
"""
- with open('/proc/' + pid + '/cmdline') as file:
- try:
- return file.readlines()[0].replace('\x00', ' ').strip()
- except IndexError:
- return ''
+ with open('/proc/' + pid + '/cmdline') as f:
+ return f.read().replace('\x00', ' ').rstrip()
def pid_to_uid(pid):
'''return euid'''
- with open('/proc/' + pid + '/status') as f:
- for n, line in enumerate(f):
- if n is uid_index:
- return line.split('\t')[2]
+ try:
+ with open('/proc/' + pid + '/status') as f:
+ for n, line in enumerate(f):
+ if n is uid_index:
+ return line.split('\t')[2]
+ except UnicodeDecodeError:
+ with open('/proc/' + pid + '/status', 'rb') as f:
+ f_list = f.read().decode('utf-8', 'ignore').split('\n')
+ return f_list[uid_index].split('\t')[2]
def notify_send_wait(title, body):
+ '''GUI notifications with UID != 0'''
with Popen(['notify-send', '--icon=dialog-warning', title, body]) as proc:
try:
proc.wait(timeout=wait_time)
@@ -287,6 +299,7 @@ def notify_send_wait(title, body):
def notify_helper(title, body):
+ '''GUI notification with UID = 0'''
with Popen([notify_helper_path, title, body]) as proc:
try:
proc.wait(timeout=wait_time)
@@ -342,8 +355,8 @@ def send_notify(signal, name, pid):
title = 'Preventing OOM'
body = '{} process {}, {}'.format(
notify_sig_dict[signal], pid, name.replace(
- # сивол & может ломать уведомления в некоторых темах оформления,
- # поэтому заменяется на *
+ # symbol '&' can break notifications in some themes,
+ # therefore it is replaced by '*'
'&', '*'))
if root:
# send notification to all active users with notify-send
@@ -353,6 +366,27 @@ def send_notify(signal, name, pid):
notify_send_wait(title, body)
+'''
+def send_notify(signal, name, pid):
+ """
+ Notificate about OOM Preventing.
+
+ signal: key for notify_sig_dict
+ name: str process name
+ pid: str process pid
+ """
+ title = 'Preventing OOM'
+ body = '{} process {}, {}'.format(
+ notify_sig_dict[signal], pid, name)
+ if root:
+ # send notification to all active users with notify-send
+ notify_helper(title, body)
+ else:
+ # send notification to user that runs this nohang
+ notify_send_wait(title, body)
+'''
+
+
def send_notify_etc(pid, name, command):
"""
Notificate about OOM Preventing.
@@ -472,6 +506,7 @@ def find_victim_and_send_signal(signal):
# Get VmRSS and VmSwap and cmdline of victim process and try to send
# signal
try:
+
with open('/proc/' + pid + '/status') as f:
for n, line in enumerate(f):
@@ -516,24 +551,67 @@ def find_victim_and_send_signal(signal):
except FileNotFoundError:
print(mem_info)
- print('The victim died in the search process')
- update_stat_dict_and_print('The victim died in the search process')
+ 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')
- update_stat_dict_and_print('The victim died in the search process')
+ 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:
+
+ # тут надо снова все исключ обработать
+
+ with open('/proc/' + pid + '/status', 'rb') as f:
+ f_list = f.read().decode('utf-8', 'ignore').split('\n')
+
+ for i in range(len(f_list)):
+ if i is uid_index:
+ 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]))
+
+ if i is vm_rss_index:
+ vm_rss = kib_to_mib(int(f_list[i].split('\t')[1][:-3]))
+
+ if detailed_rss:
+
+ if i is anon_index:
+ anon_rss = kib_to_mib(
+ int(f_list[i].split('\t')[1][:-3]))
+
+ if i is file_index:
+ file_rss = kib_to_mib(
+ int(f_list[i].split('\t')[1][:-3]))
+
+ if i is shmem_index:
+ shmem_rss = kib_to_mib(
+ 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]))
+
+
+ with open('/proc/' + pid + '/cmdline') as file:
+ cmdline = file.readlines()[0].replace('\x00', ' ')
+
+ oom_score = rline1('/proc/' + pid + '/oom_score')
+ oom_score_adj = rline1('/proc/' + pid + '/oom_score_adj')
+
except IndexError:
print(mem_info)
- print('The victim died in the search process')
- update_stat_dict_and_print('The victim died in the search process')
+ 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')
- update_stat_dict_and_print('The victim died in the search process')
+ 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:
diff --git a/nohang.conf b/nohang.conf
index c9ba7a1..c0096d4 100644
--- a/nohang.conf
+++ b/nohang.conf
@@ -132,7 +132,7 @@ min_delay_after_sigkill = 1
Valid values are True and False.
Values are case sensitive.
-decrease_oom_score_adj = False
+decrease_oom_score_adj = True
Valid values are integers from the range [0; 1000].
@@ -160,7 +160,7 @@ oom_score_adj_max = 30
Valid values are True and False.
-regex_matching = False
+regex_matching = True
Syntax:
@@ -184,7 +184,7 @@ regex_matching = False
A good option that allows fine adjustment.
-re_match_cmdline = False
+re_match_cmdline = True
@CMDLINE_RE 300 /// -childID|--type=renderer
@@ -195,7 +195,7 @@ re_match_cmdline = False
The most slow option
-re_match_uid = False
+re_match_uid = True
@UID_RE -100 /// ^0$
@@ -215,7 +215,7 @@ re_match_uid = False
Valid values are True and False.
-execute_the_command = False
+execute_the_command = True
The length of the process name can't exceed 15 characters.
The syntax is as follows: lines starting with keyword $ETC are
@@ -240,7 +240,7 @@ execute_the_command = False
Also $NAME will be replaced by process name.
-$ETC bash /// kill -9 $PID
+ $ETC bash /// kill -9 $PID
$ETC firefox-esr /// kill -SEGV $PID
#####################################################################
@@ -258,12 +258,12 @@ $ETC firefox-esr /// kill -SEGV $PID
See also wiki.archlinux.org/index.php/Desktop_notifications
Valid values are True and False.
-gui_notifications = False
+gui_notifications = True
Enable GUI notifications about the low level of available memory.
Valid values are True and False.
-gui_low_memory_warnings = False
+gui_low_memory_warnings = True
Минимальное время между отправками уведомлений в секундах.
Valid values are floating-point numbers from the range [1; 300].
diff --git a/nohang_notify_helper b/nohang_notify_helper
index f2aade0..1bdd311 100755
--- a/nohang_notify_helper
+++ b/nohang_notify_helper
@@ -3,7 +3,7 @@
# Usage:
# ./nohang_notify_helper "title" "body"
-from sys import argv
+from sys import argv, stdout
from os import listdir
from subprocess import Popen, TimeoutExpired
@@ -93,10 +93,17 @@ def root_notify_env():
list_with_envs = root_notify_env()
+list_len = len(list_with_envs)
# if somebody logged in with GUI
-if len(list_with_envs) > 0:
+if list_len > 0:
+
+ for i in list_with_envs:
+ print('Send GUI notification:', argv[1], argv[2], i)
+
+ stdout.flush()
+
# iterating over logged-in users
for i in list_with_envs:
username, display_env, dbus_env = i[0], i[1], i[2]
@@ -118,4 +125,6 @@ if len(list_with_envs) > 0:
proc.kill()
print('TimeoutExpired: notify user:' + username)
else:
- print('Nobody logged-in with GUI. Nothing to do.')
+ print('Not send GUI notification: [', argv[1], argv[2], ']. Nobody logged-in with GUI. Nothing to do.')
+
+stdout.flush()