This is an automated email from the git hooks/post-receive script. x2go pushed a commit to branch master in repository x2goserver. commit cee48577633c72988dd8563ceae7bf04cfe7d518 Author: Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> Date: Wed Jun 25 16:43:16 2014 +0200 x2gostartagent, x2golistsession, x2gosuspend-session and x2goresume-session getting agent state from ~/.x2go/C-$SID/state. This should help to avoid session damage. (Fixes: #302). --- X2Go/Server/Agent.pm | 6 +- X2Go/Server/Agent/NX.pm | 76 +++++++------------- debian/changelog | 5 ++ debian/control | 1 + x2goserver/bin/x2golistsessions | 10 ++- x2goserver/bin/x2goresume-session | 55 ++++++++++++++ x2goserver/bin/x2gostartagent | 6 +- x2goserver/bin/x2gosuspend-session | 37 +++++----- .../Agent.pm => x2goserver/lib/x2gogetagentstate | 46 +++--------- 9 files changed, 135 insertions(+), 107 deletions(-) diff --git a/X2Go/Server/Agent.pm b/X2Go/Server/Agent.pm index 4641ec0..42d753e 100644 --- a/X2Go/Server/Agent.pm +++ b/X2Go/Server/Agent.pm @@ -42,7 +42,7 @@ load_module $agent_module; use base 'Exporter'; -our @EXPORT=( 'session_has_terminated', 'session_is_running', 'session_is_suspended' ); +our @EXPORT=( 'session_has_terminated', 'session_is_running', 'session_is_suspended' , 'get_agent_state'); @@ -60,4 +60,8 @@ sub session_is_suspended { return $agent_module->session_is_suspended(@_); } +sub get_agent_state { + return $agent_module->get_agent_state(@_); +} + 1; diff --git a/X2Go/Server/Agent/NX.pm b/X2Go/Server/Agent/NX.pm index 1329f5b..7242474 100644 --- a/X2Go/Server/Agent/NX.pm +++ b/X2Go/Server/Agent/NX.pm @@ -31,10 +31,9 @@ X2Go::Server::Agent::NX Perl package for X2Go::Server. =cut use strict; -use DBI; use POSIX; use Sys::Syslog qw( :standard :macros ); -use File::ReadBackwards; +use File::HomeDir; use X2Go::Log qw( loglevel ); @@ -43,22 +42,8 @@ setlogmask( LOG_UPTO(loglevel()) ); sub session_has_terminated { - my $sess=shift; - my $user=shift; - my $log; - if ( -d "/tmp-inst/${user}/.x2go-${user}" ) { - $log="/tmp-inst/${user}/.x2go-${user}/session-C-${sess}.log"; - } else { - $log="/tmp/.x2go-${user}/session-C-${sess}.log"; - } - my $log_line; - my $log_file = File::ReadBackwards->new( $log ) or return 1; - while( defined( $log_line = $log_file->readline ) ) { - next if ( ! ( $log_line =~ m/^Session:/ ) ); - last; - } - $log_file->close(); - if (($log_line =~ m/Session terminated/) || ($log_line =~ m/Terminating session/) || ($log_line =~ m/Aborting session/)) + my $state=get_agent_state(@_); + if(($state eq 'TERMINATING')||($state eq 'TERMINATED')) { return 1; } @@ -68,22 +53,8 @@ sub session_has_terminated sub session_is_suspended { - my $sess=shift; - my $user=shift; - my $log; - if ( -d "/tmp-inst/${user}/.x2go-${user}" ) { - $log="/tmp-inst/${user}/.x2go-${user}/session-C-${sess}.log"; - } else { - $log="/tmp/.x2go-${user}/session-C-${sess}.log"; - } - my $log_line; - my $log_file = File::ReadBackwards->new( $log ) or return 0; - while( defined( $log_line = $log_file->readline ) ) { - next if ( ! ( $log_line =~ m/^Session:/ ) ); - last; - } - $log_file->close(); - if (($log_line =~ m/Session suspended/) || ($log_line =~ m/Suspending session/) || ($log_line =~ m/Display failure detected/)) + my $state=get_agent_state(@_); + if(($state eq 'SUSPENDING')||($state eq 'SUSPENDED')) { return 1; } @@ -93,26 +64,31 @@ sub session_is_suspended sub session_is_running { - my $sess=shift; - my $user=shift; - my $log; - if ( -d "/tmp-inst/${user}/.x2go-${user}" ) { - $log="/tmp-inst/${user}/.x2go-${user}/session-C-${sess}.log"; - } else { - $log="/tmp/.x2go-${user}/session-C-${sess}.log"; - } - my $log_line; - my $log_file = File::ReadBackwards->new( $log ) or return 0; - while( defined( $log_line = $log_file->readline ) ) { - next if ( ! ( $log_line =~ m/^Session:/ ) ); - last; - } - $log_file->close(); - if (($log_line =~ m/Session started/) || ($log_line =~ m/Starting session/) || ($log_line =~ m/Session resumed/) || ($log_line =~ m/Resuming session/)) + my $state=get_agent_state(@_); + if(($state eq 'STARTING')||($state eq 'RESUMING')||($state eq 'RUNNING')) { return 1; } return 0; } +sub get_agent_state +{ + my $sess=@_[1]; + my $user=@_[2]; + my $state; + my $stateFile = File::HomeDir->users_home($user) . "/.x2go/C-".$sess."/state"; + if (! -e $stateFile ) + { + die "state file not exists: $stateFile\n"; + } + else + { + open(F,"<$stateFile"); + $state=<F>; + close(F); + } + return $state; +} + 1; diff --git a/debian/changelog b/debian/changelog index 2f9906f..5a0fc35 100644 --- a/debian/changelog +++ b/debian/changelog @@ -114,6 +114,11 @@ x2goserver (4.1.0.0-0x2go1.1) UNRELEASED; urgency=low * New upstream version (4.1.0.0): - Use new script x2gopath in Perl::API. (Fixes: #86). + [ Oleksandr Shneyder ] + * x2gostartagent, x2golistsession, x2gosuspend-session and x2goresume-session + getting agent state from ~/.x2go/C-$SID/state. This should help to avoid + session damage. (Fixes: #302). + -- Mike Gabriel <mike.gabriel@das-netzwerkteam.de> Fri, 09 May 2014 13:06:24 +0200 x2goserver (4.0.1.16-0x2go1) UNRELEASED; urgency=low diff --git a/debian/control b/debian/control index 373738e..5976f26 100644 --- a/debian/control +++ b/debian/control @@ -21,6 +21,7 @@ Depends: ${misc:Depends}, libfile-basedir-perl, libfile-readbackwards-perl, + libfile-homedir-perl, libtry-tiny-perl, libx2go-server-perl (>= ${source:Version}), libx2go-server-perl (<< ${source:Version}.1~), x2goagent (>= 2:3.5.0.25-0~), diff --git a/x2goserver/bin/x2golistsessions b/x2goserver/bin/x2golistsessions index eb6f78c..e5cff26 100755 --- a/x2goserver/bin/x2golistsessions +++ b/x2goserver/bin/x2golistsessions @@ -27,7 +27,7 @@ use Sys::Syslog qw( :standard :macros ); use File::ReadBackwards; use X2Go::Server::DB qw(db_listsessions db_listsessions_all db_changestatus); -use X2Go::Server::Agent qw(session_is_suspended); +use X2Go::Server::Agent qw(session_is_suspended session_is_running); use X2Go::Log qw(loglevel); @@ -81,6 +81,14 @@ for (my $i=0;$i<@outp;$i++) system("x2goumount-session", "@sinfo[1]"); } } + elsif (@sinfo[4]eq 'S') + { + if(session_is_running(@sinfo[1], @sinfo[11])) + { + db_changestatus( 'R', @sinfo[1] ); + @outp[$i] =~ s/\|S\|/\|R\|/; + } + } print "@outp[$i]\n"; } } diff --git a/x2goserver/bin/x2goresume-session b/x2goserver/bin/x2goresume-session index b536434..84f31ec 100755 --- a/x2goserver/bin/x2goresume-session +++ b/x2goserver/bin/x2goresume-session @@ -20,6 +20,12 @@ # Copyright (C) 2007-2014 Oleksandr Shneyder <oleksandr.shneyder@obviously-nice.de> # Copyright (C) 2007-2014 Heinz-Markus Graesing <heinz-m.graesing@obviously-nice.de> +if [ $# -lt 7 ] +then + echo "not enough arguments" + exit -1 +fi + SESSION_NAME="$1" X2GO_GEOMETRY="$2" X2GO_LINK="$3" @@ -35,6 +41,55 @@ X2GO_ROOT="${HOME}/.x2go" X2GO_RESIZE=0 X2GO_FULLSCREEN=0 + +STATE=`$X2GO_LIB_PATH/x2gogetagentstate "$SESSION_NAME"` + +# exit if session terminated +if [ "$STATE" == "TERMINATED" ] || [ "$STATE" == "TERMINATING" ] +then + echo "Session terminated" + exit -1 +fi + +i=0 +# wait 15 sec. for starting session +while [ "$STATE" == "RESUMING" ] || [ "$STATE" == "STARTING" ] +do + sleep 1 + i=$(($i+1)) + #if session still not started, try to suspend it + if [ $i -gt 15 ] + then + x2gosuspend-session "$SESSION_NAME" + sleep 2 + i=0 + fi + STATE=`$X2GO_LIB_PATH/x2gogetagentstate "$SESSION_NAME"` +done + +#suspend running session +if [ "$STATE" == "RUNNING" ] +then + x2gosuspend-session "$SESSION_NAME" + sleep 2 + STATE=`$X2GO_LIB_PATH/x2gogetagentstate "$SESSION_NAME"` +fi + +i=0 +# wait 45 sec., while session suspending +while [ "$STATE" == "SUSPENDING" ] +do + sleep 1 + i=$(($i+1)) + if [ $i -gt 45 ] + then + echo "Error: taking too long to suspend session. Possible session is damaged" + exit -1; + fi + STATE=`$X2GO_LIB_PATH/x2gogetagentstate "$SESSION_NAME"` +done + + NX_XINERAMA_CONF="$X2GO_ROOT/C-$SESSION_NAME/xinerama.conf" if [ -e "$NX_XINERAMA_CONF" ] then diff --git a/x2goserver/bin/x2gostartagent b/x2goserver/bin/x2gostartagent index bf21f7f..3f82c7f 100755 --- a/x2goserver/bin/x2gostartagent +++ b/x2goserver/bin/x2gostartagent @@ -252,6 +252,8 @@ if [ "x$X2GO_TELEKINESIS_ENABLED" != "x0" ]; then mkdir -p "${SESSION_DIR}/telekinesis/remote/" fi +STATE_FILE="${X2GO_ROOT}/C-${SESSION_NAME}/state" + # do not use $TMP or $TEMP here, the session.log file location has to be accessible by root SESSION_LOG="/tmp/.x2go-${USER}/session-C-${SESSION_NAME}.log" mkdir -p $(dirname "${SESSION_LOG}") @@ -288,9 +290,9 @@ if [ -n "$X2GO_GEOMETRY" ] && [ "$X2GO_GEOMETRY" != "fullscreen" ]; then fi if [ "$X2GO_SET_KBD" == "0" ] || [ "$X2GO_KBD_TYPE" == "auto" ];then - X2GO_HOST="nx/nx,link=${X2GO_LINK},pack=${X2GO_PACK},limit=0,root=${SESSION_DIR},cache=8M,images=32M,type=${X2GO_TYPE},id=${SESSION_NAME},cookie=$X2GO_COOKIE,errors=${SESSION_LOG},kbtype=null/null,${option_geometry}resize=${X2GO_RESIZE},fullscreen=${X2GO_FULLSCREEN},accept=${REMOTE},listen=${GR_PORT},client=linux,menu=0" + X2GO_HOST="nx/nx,link=${X2GO_LINK},pack=${X2GO_PACK},limit=0,root=${SESSION_DIR},cache=8M,images=32M,type=${X2GO_TYPE},id=${SESSION_NAME},cookie=$X2GO_COOKIE,errors=${SESSION_LOG},kbtype=null/null,${option_geometry}resize=${X2GO_RESIZE},fullscreen=${X2GO_FULLSCREEN},accept=${REMOTE},listen=${GR_PORT},client=linux,menu=0,state=${STATE_FILE}" else - X2GO_HOST="nx/nx,link=${X2GO_LINK},pack=${X2GO_PACK},limit=0,root=${SESSION_DIR},cache=8M,images=32M,type=${X2GO_TYPE},id=${SESSION_NAME},cookie=$X2GO_COOKIE,errors=${SESSION_LOG},kbtype=${X2GO_KBD_TYPE},${option_geometry}resize=${X2GO_RESIZE},fullscreen=${X2GO_FULLSCREEN},accept=${REMOTE},listen=${GR_PORT},client=linux,menu=0" + X2GO_HOST="nx/nx,link=${X2GO_LINK},pack=${X2GO_PACK},limit=0,root=${SESSION_DIR},cache=8M,images=32M,type=${X2GO_TYPE},id=${SESSION_NAME},cookie=$X2GO_COOKIE,errors=${SESSION_LOG},kbtype=${X2GO_KBD_TYPE},${option_geometry}resize=${X2GO_RESIZE},fullscreen=${X2GO_FULLSCREEN},accept=${REMOTE},listen=${GR_PORT},client=linux,menu=0,state=${STATE_FILE}" fi diff --git a/x2goserver/bin/x2gosuspend-session b/x2goserver/bin/x2gosuspend-session index 9fc5d48..9f7f61f 100755 --- a/x2goserver/bin/x2gosuspend-session +++ b/x2goserver/bin/x2gosuspend-session @@ -54,26 +54,29 @@ x2gofeature X2GO_RUN_EXTENSIONS &>/dev/null && x2goserver-run-extensions "$SESSI export HOSTNAME x2goumount-session "$SESSION_NAME" -if kill -HUP $X2GO_AGENT_PID &>/dev/null; then - $X2GO_LIB_PATH/x2gosyslog "$0" "notice" "session with ID $SESSION_NAME has been suspended successfully" +STATE=`$X2GO_LIB_PATH/x2gogetagentstate "$SESSION_NAME"` - # run x2goserver-extensions for post-suspend - x2gofeature X2GO_RUN_EXTENSIONS &>/dev/null && x2goserver-run-extensions "$SESSION_NAME" post-suspend || true +if [ "$STATE" == "RESUMING" ] || [ "$STATE" == "STARTING" ] || [ "$STATE" == "RUNNING" ] +then + if kill -HUP $X2GO_AGENT_PID &>/dev/null; then + $X2GO_LIB_PATH/x2gosyslog "$0" "notice" "session with ID $SESSION_NAME has been suspended successfully" - $X2GO_LIB_PATH/x2gochangestatus 'S' "$SESSION_NAME" > /dev/null + # run x2goserver-extensions for post-suspend + x2gofeature X2GO_RUN_EXTENSIONS &>/dev/null && x2goserver-run-extensions "$SESSION_NAME" post-suspend || true - # this makes sure that the socket on localhost blocked by NX agent gets released immediately - $X2GO_LIB_PATH/x2gonxcleanup -else - err_msg="ERROR: failed to suspend session with ID $SESSION_NAME" - echo "$err_msg" 1>&2 - $X2GO_LIB_PATH/x2gosyslog "$0" "err" "$err_msg" + $X2GO_LIB_PATH/x2gochangestatus 'S' "$SESSION_NAME" > /dev/null + else + err_msg="ERROR: failed to suspend session with ID $SESSION_NAME" + echo "$err_msg" 1>&2 + $X2GO_LIB_PATH/x2gosyslog "$0" "err" "$err_msg" - # run x2goserver-extensions for fail-suspend - x2gofeature X2GO_RUN_EXTENSIONS &>/dev/null && x2goserver-run-extensions "$SESSION_NAME" fail-suspend || true + # run x2goserver-extensions for fail-suspend + x2gofeature X2GO_RUN_EXTENSIONS &>/dev/null && x2goserver-run-extensions "$SESSION_NAME" fail-suspend || true - # If we reach here it means that the x2goagent process of the session has vanisshed - # If this happens then we mark the session as finished... - $X2GO_LIB_PATH/x2gochangestatus 'F' "$SESSION_NAME" > /dev/null + # If we reach here it means that the x2goagent process of the session has vanisshed + # If this happens then we mark the session as finished... + $X2GO_LIB_PATH/x2gochangestatus 'F' "$SESSION_NAME" > /dev/null + fi +else + $X2GO_LIB_PATH/x2gosyslog "$0" "notice" "session with ID $SESSION_NAME is not in running state" fi - diff --git a/X2Go/Server/Agent.pm b/x2goserver/lib/x2gogetagentstate old mode 100644 new mode 100755 similarity index 54% copy from X2Go/Server/Agent.pm copy to x2goserver/lib/x2gogetagentstate index 4641ec0..b84d764 --- a/X2Go/Server/Agent.pm +++ b/x2goserver/lib/x2gogetagentstate @@ -1,3 +1,5 @@ +#!/usr/bin/perl + # Copyright (C) 2007-2014 X2Go Project - http://wiki.x2go.org # # This program is free software; you can redistribute it and/or modify @@ -18,46 +20,18 @@ # Copyright (C) 2007-2014 Oleksandr Shneyder <oleksandr.shneyder@obviously-nice.de> # Copyright (C) 2007-2014 Heinz-Markus Graesing <heinz-m.graesing@obviously-nice.de> -package X2Go::Server::Agent; - -=head1 NAME - -X2Go::Server::Agent - X2Go Server Agent package for Perl - -=head1 DESCRIPTION - -X2Go::Server::Agent Perl package for X2Go::Server. - -=cut - use strict; -use X2Go::Utils qw( load_module ); - -# TODO: when other agents may come into play, the AGENT var has to be read from config file or -# somehow else... -my $DEFAULT_AGENT="NX"; -my $AGENT=$DEFAULT_AGENT; -my $agent_module = "X2Go::Server::Agent::$AGENT"; -load_module $agent_module; - -use base 'Exporter'; - -our @EXPORT=( 'session_has_terminated', 'session_is_running', 'session_is_suspended' ); - - -sub session_has_terminated { - return $agent_module->session_has_terminated(@_); -} +#use strict; +#use Sys::Hostname; +#use Sys::Syslog qw( :standard :macros ); -sub session_is_running { - return $agent_module->session_is_running(@_); -} +use X2Go::Server::DB; +use X2Go::Server::Agent; -sub session_is_suspended { - return $agent_module->session_is_suspended(@_); -} +my $sid=shift or die "argument session id missed"; +my $user=getpwuid($<); -1; +print get_agent_state($sid, $user); -- Alioth's /srv/git/_hooks_/post-receive-email on /srv/git/code.x2go.org/x2goserver.git