четверг, 25 февраля 2016 г.

Java и неоканчивающийся процесс.

Так уж вышло, что мне приходится использовать SAP GUI по работе. Написан он на java, который я очень сильно недолюбливаю, хотя это уже совсем другая история. ;) Всё бы ничего и с мелкими багами SAPGUI мириться вполне можно, но одна вещь меня очень сильно раздражала: когда я выхожу из этих долбаных gui, процесс java остаётся висеть в памяти. :( В один прекрасный момент меня это крепко достало.

Первым был сделан очень простой костыль: после запуска запоминался PID процесса и выкидывалось окошко (я использовал zenity, можно в принципе что угодно применить). После выхода из SAP всё что нужно было сделать - это нажать в этом окошке OK. Не самое лучшее решение, но простое и работающее:

_JAVA_AWT_WM_NONREPARENTING=1; export _JAVA_AWT_WM_NONREPARENTING
AWT_TOOLKIT=MToolkit; export AWT_TOOLKIT

sapguistart /H/xxxxx/H/xxxxx/S/3262$LOGSTRING > /dev/null 2>&1 &
PID=$$
zenity --info --text="Press OK to exit from SAP"
pkill -P $PID; exit

trap "pkill -P $PID; exit" SIGINT
trap "pkill -P $PID; exit" SIGTERM
trap "pkill -P $PID; exit" EXIT

Потом я решил всё же разобраться в чём проблема. strace рассказал, конечно, много чего, но в целом все поиски по инету не привели ни к чему хорошему, кроме как к срачу между разрабами java и всеми остальными: первые кричат что это не проблема java, вторые очень с ними не согласны. Срач тянется года с 2004, а воз и ныне там.
Сие обстоятельство конечно сильно огорчило, так как всё же пришлось делать костыли. Но как и любые костыли во всех unix и unix like системах они работают и работают отлично! ;) Всё что требуется помимо стандартного шела - это xdotool:

_JAVA_AWT_WM_NONREPARENTING=1; export _JAVA_AWT_WM_NONREPARENTING
AWT_TOOLKIT=MToolkit; export AWT_TOOLKIT

sapguistart /H/xxxxx/H/xxxxx/S/3262$LOGSTRING > /dev/null 2>&1 &
PID=$$

while true
do
    sleep 5
    xdotool search "SAPGUI" > /dev/null 2>&1 ; ERR=$?
    if [ $ERR -ne 0 ]; then
        pkill -P $PID; exit
    fi
done

trap "pkill -P $PID; exit" SIGINT
trap "pkill -P $PID; exit" SIGTERM
trap "pkill -P $PID; exit" EXIT

Такой метод в принципе позволяет убивать любые зависающие процессы, окна которых закрываются, но сам процесс остаётся висеть в памяти.

В общем писал как обычно для себя, но если кому пригодится - буду только рад. ;)