fix GUI notifications

This commit is contained in:
Alexey Avramov 2019-03-21 06:32:59 +09:00
parent 2f4b89ff51
commit 74a20ce28e
3 changed files with 59 additions and 81 deletions

87
nohang
View File

@ -41,7 +41,7 @@ if self_uid == 0:
else: else:
root = False root = False
wait_time = 10 # wait_time = 10
notify_helper_path = '/usr/sbin/nohang_notify_helper' notify_helper_path = '/usr/sbin/nohang_notify_helper'
@ -63,18 +63,12 @@ separate_log = False # will be overwritten after parse config
# define functions # define functions
def func_print_proc_table(): def func_print_proc_table():
print_proc_table = True print_proc_table = True
find_victim(print_proc_table) find_victim(print_proc_table)
exit() exit()
def log(*msg): def log(*msg):
""" """
""" """
@ -282,6 +276,12 @@ def check_mem():
return int(rline1('/proc/meminfo').split(':')[1][:-4]) return int(rline1('/proc/meminfo').split(':')[1][:-4])
def write(text):
file = '/dev/shm/nohang_notify'
with open(file, 'w') as f:
f.write(text)
def check_mem_and_swap(): def check_mem_and_swap():
"""find mem_available, swap_total, swap_free""" """find mem_available, swap_total, swap_free"""
with open('/proc/meminfo') as f: with open('/proc/meminfo') as f:
@ -560,29 +560,6 @@ def pid_to_uid(pid):
return f_list[uid_index].split('\t')[2] 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)
except TimeoutExpired:
proc.kill()
print('TimeoutExpired: notify-send {} {}'.format(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)
except TimeoutExpired:
proc.kill()
print(
'TimeoutExpired: nohang_notify_helper: {} {}'.format(
title, body))
def send_notify_warn(): def send_notify_warn():
""" """
Look for process with maximum 'badness' and warn user with notification. Look for process with maximum 'badness' and warn user with notification.
@ -613,7 +590,7 @@ def send_notify_warn():
''' '''
''' '''
body = 'Next victim: {}[{}]'.format( body2 = 'Next victim: {}[{}]'.format(
name.replace( name.replace(
# symbol '&' can break notifications in some themes, # symbol '&' can break notifications in some themes,
# therefore it is replaced by '*' # therefore it is replaced by '*'
@ -634,18 +611,19 @@ def send_notify_warn():
# send notification to user that runs this nohang # send notification to user that runs this nohang
notify_send_wait(title, body) notify_send_wait(title, body)
''' '''
#os.system('echo --- \ - $(sleep 5) - ')
b = """{} 'Low memory' 'MemAvail: {}%\nSwapFree: {}%' &""".format( t0 = time()
notify_helper_path,
title = 'Low memoy'
body = 'MemAvail: {}%\nSwapFree: {}%'.format(
round(mem_available / mem_total * 100), round(mem_available / mem_total * 100),
round(swap_free / (swap_total + 0.1) * 100) round(swap_free / (swap_total + 0.1) * 100)
) )
write('{}\x00{}'.format(title, body))
b = 'head ' + str(b.encode()) os.system(notify_helper_path + ' &')
t0 = time()
os.system(b)
t1 = time() t1 = time()
print('t:', t1 - t0) print('t:', t1 - t0)
@ -667,12 +645,18 @@ def send_notify(signal, name, pid):
'&', '*' '&', '*'
) )
) )
write('{}\x00{}'.format(title, body))
os.system(notify_helper_path + ' &')
'''
if root: if root:
# send notification to all active users with notify-send # send notification to all active users with notify-send
notify_helper(title, body) notify_helper(title, body)
else: else:
# send notification to user that runs this nohang # send notification to user that runs this nohang
notify_send_wait(title, body) notify_send_wait(title, body)
'''
def send_notify_etc(pid, name, command): def send_notify_etc(pid, name, command):
@ -689,12 +673,17 @@ def send_notify_etc(pid, name, command):
pid, pid,
command.replace('&', '*') command.replace('&', '*')
) )
write('{}\x00{}'.format(title, body))
os.system(notify_helper_path + ' &')
'''
if root: if root:
# send notification to all active users with notify-send # send notification to all active users with notify-send
notify_helper(title, body) notify_helper(title, body)
else: else:
# send notification to user that runs this nohang # send notification to user that runs this nohang
notify_send_wait(title, body) notify_send_wait(title, body)
'''
def sleep_after_send_signal(signal): def sleep_after_send_signal(signal):
@ -709,7 +698,7 @@ def sleep_after_send_signal(signal):
sleep(min_delay_after_sigkill) sleep(min_delay_after_sigkill)
else: else:
if print_sleep_periods: if print_sleep_periods:
print( log(
'Sleep {} sec after implementing a corrective action'.format( 'Sleep {} sec after implementing a corrective action'.format(
min_delay_after_sigterm)) min_delay_after_sigterm))
sleep(min_delay_after_sigterm) sleep(min_delay_after_sigterm)
@ -1855,21 +1844,10 @@ if max_sleep_time < min_sleep_time:
exit(1) exit(1)
if print_proc_table_flag: if print_proc_table_flag:
func_print_proc_table() func_print_proc_table()
########################################################################## ##########################################################################
@ -1951,10 +1929,6 @@ else:
########################################################################## ##########################################################################
if print_config: if print_config:
print( print(
@ -2034,8 +2008,7 @@ if print_config:
# for calculating the column width when printing mem and zram # for calculating the column width when printing mem and zram
mem_len = len(str(round(mem_total / 1024.0))) mem_len = len(str(round(mem_total / 1024.0)))
if gui_notifications or gui_low_memory_warnings: if gui_notifications:
from subprocess import Popen, TimeoutExpired
notify_sig_dict = {SIGKILL: 'Killing', notify_sig_dict = {SIGKILL: 'Killing',
SIGTERM: 'Terminating'} SIGTERM: 'Terminating'}
@ -2061,7 +2034,7 @@ mlockall()
if print_proc_table: if print_proc_table:
find_victim() find_victim(print_proc_table)
log('Monitoring started!') log('Monitoring started!')

View File

@ -178,7 +178,7 @@ decrease_oom_score_adj = False
Valid values are integers from the range [0; 1000]. Valid values are integers from the range [0; 1000].
oom_score_adj_max = 30 oom_score_adj_max = 20
##################################################################### #####################################################################

View File

@ -3,15 +3,10 @@
# Usage: # Usage:
# ./nohang_notify_helper "title" "body" # ./nohang_notify_helper "title" "body"
from sys import argv, stdout
from os import listdir, path from os import listdir, path
from subprocess import Popen, TimeoutExpired from subprocess import Popen, TimeoutExpired
if len(argv) < 2 or argv[1] == "-h" or argv[1] == "--help": wait_time = 10
print('Usage: ./nohang_notify_helper "title" "body"')
exit(1)
wait_time = 15
display_env = 'DISPLAY=' display_env = 'DISPLAY='
dbus_env = 'DBUS_SESSION_BUS_ADDRESS=' dbus_env = 'DBUS_SESSION_BUS_ADDRESS='
@ -25,6 +20,15 @@ def rline1(path):
return line return line
def rfile(path):
"""read file."""
with open(path) as f:
return f.read()
a1, a2 = rfile('/dev/shm/nohang_notify').split('\x00')
def re_pid_environ(pid): def re_pid_environ(pid):
""" """
read environ of 1 process read environ of 1 process
@ -108,9 +112,7 @@ list_len = len(list_with_envs)
if list_len > 0: if list_len > 0:
for i in list_with_envs: for i in list_with_envs:
print('Send GUI notification:', argv[1], argv[2], i) print('Send GUI notification:', a1, a2, 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:
@ -125,7 +127,10 @@ if list_len > 0:
'env', 'env',
'DISPLAY=' + display_value, 'DISPLAY=' + display_value,
'DBUS_SESSION_BUS_ADDRESS=' + dbus_value, 'DBUS_SESSION_BUS_ADDRESS=' + dbus_value,
'notify-send', '--icon=dialog-warning', argv[1], argv[2] 'notify-send',
'--icon=dialog-warning',
a1,
a2
]) as proc: ]) as proc:
try: try:
proc.wait(timeout=wait_time) proc.wait(timeout=wait_time)
@ -135,6 +140,6 @@ if list_len > 0:
else: else:
print( print(
'Not send GUI notification: [', 'Not send GUI notification: [',
argv[1], a1,
argv[2], a2,
']. Nobody logged-in with GUI. Nothing to do.') ']. Nobody logged-in with GUI. Nothing to do.')