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