mosh-server: Support timeouts on lost connectivity to network client.
Closes #690.
This commit is contained in:
@@ -82,6 +82,43 @@ Locale-related environment variable to try as part of a fallback
|
|||||||
environment, if the startup environment does not specify a character
|
environment, if the startup environment does not specify a character
|
||||||
set of UTF-8.
|
set of UTF-8.
|
||||||
|
|
||||||
|
.SH ENVIRONMENT VARIABLES
|
||||||
|
These variables allow server-side configuration of Mosh's behavior.
|
||||||
|
They may be set by administrators in system login/rc files,
|
||||||
|
/etc/login.conf, or similar mechanisms, or users in their shell's
|
||||||
|
login/rc files. \fBmosh-server\fP passes these variables to the login
|
||||||
|
session and shell that it starts, but changing them there will have no
|
||||||
|
effect.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.B MOSH_SERVER_NETWORK_TMOUT
|
||||||
|
If this variable is set to a positive integer number, it specifies how
|
||||||
|
long (in seconds) \fBmosh-server\fP will wait to receive an update from the
|
||||||
|
client before exiting. Since \fPmosh\fP is very useful for mobile
|
||||||
|
clients with intermittent operation and connectivity, we suggest
|
||||||
|
setting this variable to a high value, such as 604800 (one week) or
|
||||||
|
2592000 (30 days). Otherwise, \fBmosh-server\fP will wait
|
||||||
|
indefinitely for a client to reappear. This variable is somewhat
|
||||||
|
similar to the \fBTMOUT\fP variable found in many Bourne shells.
|
||||||
|
However, it is not a login-session inactivity timeout; it only applies
|
||||||
|
to network connectivity.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.B MOSH_SERVER_SIGNAL_TMOUT
|
||||||
|
If this variable is set to a positive integer number, it specifies how
|
||||||
|
long (in seconds) \fBmosh-server\fP will ignore SIGUSR1 while waiting
|
||||||
|
to receive an update from the client. Otherwise, \fBSIGUSR1\fP will
|
||||||
|
always terminate \fBmosh-server\fP. Users and administrators may
|
||||||
|
implement scripts to clean up disconnected Mosh sessions. With this
|
||||||
|
variable set, a user or administrator can issue
|
||||||
|
|
||||||
|
.nf
|
||||||
|
$ pkill -SIGUSR1 mosh-server
|
||||||
|
.fi
|
||||||
|
|
||||||
|
to kill disconnected sessions without killing connected login
|
||||||
|
sessions.
|
||||||
|
|
||||||
.SH EXAMPLE
|
.SH EXAMPLE
|
||||||
|
|
||||||
.nf
|
.nf
|
||||||
|
|||||||
@@ -92,6 +92,13 @@ command to run server helper on remote machine (default: "mosh-server")
|
|||||||
The server helper is unprivileged and can be installed in the user's
|
The server helper is unprivileged and can be installed in the user's
|
||||||
home directory.
|
home directory.
|
||||||
|
|
||||||
|
This option can be used to set environment variables for the server by
|
||||||
|
using the
|
||||||
|
.BR env (1)
|
||||||
|
command to wrap the actual server command. See
|
||||||
|
.BR mosh-server (1)
|
||||||
|
for available environment variables.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.B \-\-ssh=\fICOMMAND\fP
|
.B \-\-ssh=\fICOMMAND\fP
|
||||||
OpenSSH command to remotely execute mosh-server on remote machine (default: "ssh")
|
OpenSSH command to remotely execute mosh-server on remote machine (default: "ssh")
|
||||||
|
|||||||
@@ -266,6 +266,8 @@ if ( (not defined $colors)
|
|||||||
$colors = 0;
|
$colors = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$ENV{ 'MOSH_CLIENT_PID' } = $$; # We don't support this, but it's useful for test and debug.
|
||||||
|
|
||||||
my $pid = open(my $pipe, "-|");
|
my $pid = open(my $pipe, "-|");
|
||||||
die "$0: fork: $!\n" unless ( defined $pid );
|
die "$0: fork: $!\n" unless ( defined $pid );
|
||||||
if ( $pid == 0 ) { # child
|
if ( $pid == 0 ) { # child
|
||||||
|
|||||||
@@ -54,6 +54,7 @@
|
|||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
#ifdef HAVE_UTMPX_H
|
#ifdef HAVE_UTMPX_H
|
||||||
#include <utmpx.h>
|
#include <utmpx.h>
|
||||||
@@ -93,7 +94,9 @@ typedef Network::Transport< Terminal::Complete, Network::UserStream > ServerConn
|
|||||||
|
|
||||||
static void serve( int host_fd,
|
static void serve( int host_fd,
|
||||||
Terminal::Complete &terminal,
|
Terminal::Complete &terminal,
|
||||||
ServerConnection &network );
|
ServerConnection &network,
|
||||||
|
long network_timeout,
|
||||||
|
long network_signaled_timeout );
|
||||||
|
|
||||||
static int run_server( const char *desired_ip, const char *desired_port,
|
static int run_server( const char *desired_ip, const char *desired_port,
|
||||||
const string &command_path, char *command_argv[],
|
const string &command_path, char *command_argv[],
|
||||||
@@ -340,6 +343,34 @@ int main( int argc, char *argv[] )
|
|||||||
static int run_server( const char *desired_ip, const char *desired_port,
|
static int run_server( const char *desired_ip, const char *desired_port,
|
||||||
const string &command_path, char *command_argv[],
|
const string &command_path, char *command_argv[],
|
||||||
const int colors, bool verbose, bool with_motd ) {
|
const int colors, bool verbose, bool with_motd ) {
|
||||||
|
/* get network idle timeout */
|
||||||
|
long network_timeout = 0;
|
||||||
|
char *timeout_envar = getenv( "MOSH_SERVER_NETWORK_TMOUT" );
|
||||||
|
if ( timeout_envar && *timeout_envar ) {
|
||||||
|
errno = 0;
|
||||||
|
char *endptr;
|
||||||
|
network_timeout = strtol( timeout_envar, &endptr, 10 );
|
||||||
|
if ( *endptr != '\0' || ( network_timeout == 0 && errno == EINVAL ) ) {
|
||||||
|
fprintf( stderr, "MOSH_SERVER_NETWORK_TMOUT not a valid integer, ignoring\n" );
|
||||||
|
} else if ( network_timeout < 0 ) {
|
||||||
|
fprintf( stderr, "MOSH_SERVER_NETWORK_TMOUT is negative, ignoring\n" );
|
||||||
|
network_timeout = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* get network signaled idle timeout */
|
||||||
|
long network_signaled_timeout = 0;
|
||||||
|
char *signal_envar = getenv( "MOSH_SERVER_SIGNAL_TMOUT" );
|
||||||
|
if ( signal_envar && *signal_envar ) {
|
||||||
|
errno = 0;
|
||||||
|
char *endptr;
|
||||||
|
network_signaled_timeout = strtol( signal_envar, &endptr, 10 );
|
||||||
|
if ( *endptr != '\0' || ( network_signaled_timeout == 0 && errno == EINVAL ) ) {
|
||||||
|
fprintf( stderr, "MOSH_SERVER_SIGNAL_TMOUT not a valid integer, ignoring\n" );
|
||||||
|
} else if ( network_signaled_timeout < 0 ) {
|
||||||
|
fprintf( stderr, "MOSH_SERVER_SIGNAL_TMOUT is negative, ignoring\n" );
|
||||||
|
network_signaled_timeout = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
/* get initial window size */
|
/* get initial window size */
|
||||||
struct winsize window_size;
|
struct winsize window_size;
|
||||||
if ( ioctl( STDIN_FILENO, TIOCGWINSZ, &window_size ) < 0 ||
|
if ( ioctl( STDIN_FILENO, TIOCGWINSZ, &window_size ) < 0 ||
|
||||||
@@ -505,7 +536,7 @@ static int run_server( const char *desired_ip, const char *desired_port,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
try {
|
try {
|
||||||
serve( master, terminal, *network );
|
serve( master, terminal, *network, network_timeout, network_signaled_timeout );
|
||||||
} catch ( const Network::NetworkException &e ) {
|
} catch ( const Network::NetworkException &e ) {
|
||||||
fprintf( stderr, "Network exception: %s\n",
|
fprintf( stderr, "Network exception: %s\n",
|
||||||
e.what() );
|
e.what() );
|
||||||
@@ -531,12 +562,16 @@ static int run_server( const char *desired_ip, const char *desired_port,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void serve( int host_fd, Terminal::Complete &terminal, ServerConnection &network )
|
static void serve( int host_fd, Terminal::Complete &terminal, ServerConnection &network, long network_timeout, long network_signaled_timeout )
|
||||||
{
|
{
|
||||||
|
/* scale timeouts */
|
||||||
|
const uint64_t network_timeout_ms = static_cast<uint64_t>( network_timeout ) * 1000;
|
||||||
|
const uint64_t network_signaled_timeout_ms = static_cast<uint64_t>( network_signaled_timeout ) * 1000;
|
||||||
/* prepare to poll for events */
|
/* prepare to poll for events */
|
||||||
Select &sel = Select::get_instance();
|
Select &sel = Select::get_instance();
|
||||||
sel.add_signal( SIGTERM );
|
sel.add_signal( SIGTERM );
|
||||||
sel.add_signal( SIGINT );
|
sel.add_signal( SIGINT );
|
||||||
|
sel.add_signal( SIGUSR1 );
|
||||||
|
|
||||||
uint64_t last_remote_num = network.get_remote_state_num();
|
uint64_t last_remote_num = network.get_remote_state_num();
|
||||||
|
|
||||||
@@ -549,14 +584,31 @@ static void serve( int host_fd, Terminal::Complete &terminal, ServerConnection &
|
|||||||
|
|
||||||
while ( 1 ) {
|
while ( 1 ) {
|
||||||
try {
|
try {
|
||||||
|
static const uint64_t timeout_if_no_client = 60000;
|
||||||
|
int timeout = INT_MAX;
|
||||||
uint64_t now = Network::timestamp();
|
uint64_t now = Network::timestamp();
|
||||||
|
|
||||||
const int timeout_if_no_client = 60000;
|
timeout = min( timeout, network.wait_time() );
|
||||||
int timeout = min( network.wait_time(), terminal.wait_time( now ) );
|
timeout = min( timeout, terminal.wait_time( now ) );
|
||||||
if ( (!network.get_remote_state_num())
|
if ( (!network.get_remote_state_num())
|
||||||
|| network.shutdown_in_progress() ) {
|
|| network.shutdown_in_progress() ) {
|
||||||
timeout = min( timeout, 5000 );
|
timeout = min( timeout, 5000 );
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
* The server goes completely asleep if it has no remote peer.
|
||||||
|
* We may want to wake up sooner.
|
||||||
|
*/
|
||||||
|
if ( network_timeout_ms ) {
|
||||||
|
int64_t network_sleep = network_timeout_ms -
|
||||||
|
( now - network.get_latest_remote_state().timestamp );
|
||||||
|
if ( network_sleep < 0 ) {
|
||||||
|
network_sleep = 0;
|
||||||
|
} else if ( network_sleep > INT_MAX ) {
|
||||||
|
/* 24 days might be too soon. That's OK. */
|
||||||
|
network_sleep = INT_MAX;
|
||||||
|
}
|
||||||
|
timeout = min( timeout, static_cast<int>(network_sleep) );
|
||||||
|
}
|
||||||
|
|
||||||
/* poll for events */
|
/* poll for events */
|
||||||
sel.clear_fds();
|
sel.clear_fds();
|
||||||
@@ -679,7 +731,20 @@ static void serve( int host_fd, Terminal::Complete &terminal, ServerConnection &
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( sel.any_signal() ) {
|
bool idle_shutdown = false;
|
||||||
|
if ( network_timeout_ms &&
|
||||||
|
network_timeout_ms <= time_since_remote_state ) {
|
||||||
|
idle_shutdown = true;
|
||||||
|
fprintf( stderr, "Network idle for %" PRIu64 " seconds.\n", time_since_remote_state / 1000 );
|
||||||
|
}
|
||||||
|
if ( sel.signal( SIGUSR1 ) ) {
|
||||||
|
if ( !network_signaled_timeout_ms || network_signaled_timeout_ms <= time_since_remote_state ) {
|
||||||
|
idle_shutdown = true;
|
||||||
|
fprintf( stderr, "Network idle for %"PRIu64" seconds when SIGUSR1 received\n", time_since_remote_state / 1000 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( sel.any_signal() || idle_shutdown ) {
|
||||||
/* shutdown signal */
|
/* shutdown signal */
|
||||||
if ( network.has_remote_addr() && (!network.shutdown_in_progress()) ) {
|
if ( network.has_remote_addr() && (!network.shutdown_in_progress()) ) {
|
||||||
network.start_shutdown();
|
network.start_shutdown();
|
||||||
@@ -736,8 +801,8 @@ static void serve( int host_fd, Terminal::Complete &terminal, ServerConnection &
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ( !network.get_remote_state_num()
|
if ( !network.get_remote_state_num()
|
||||||
&& time_since_remote_state >= uint64_t( timeout_if_no_client ) ) {
|
&& time_since_remote_state >= timeout_if_no_client ) {
|
||||||
fprintf( stderr, "No connection within %d seconds.\n",
|
fprintf( stderr, "No connection within %" PRIu64 " seconds.\n",
|
||||||
timeout_if_no_client / 1000 );
|
timeout_if_no_client / 1000 );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,9 +12,11 @@ displaytests = \
|
|||||||
emulation-80th-column.test \
|
emulation-80th-column.test \
|
||||||
emulation-back-tab.test \
|
emulation-back-tab.test \
|
||||||
emulation-multiline-scroll.test \
|
emulation-multiline-scroll.test \
|
||||||
window-resize.test \
|
server-network-timeout.test \
|
||||||
|
server-signal-timeout.test \
|
||||||
unicode-combine-fallback-assert.test \
|
unicode-combine-fallback-assert.test \
|
||||||
unicode-later-combining.test
|
unicode-later-combining.test \
|
||||||
|
window-resize.test
|
||||||
|
|
||||||
check_PROGRAMS = ocb-aes encrypt-decrypt base64
|
check_PROGRAMS = ocb-aes encrypt-decrypt base64
|
||||||
TESTS = ocb-aes encrypt-decrypt base64 $(displaytests)
|
TESTS = ocb-aes encrypt-decrypt base64 $(displaytests)
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
# then captures screen with `tmux capture-pane`. Captures exitstatus
|
# then captures screen with `tmux capture-pane`. Captures exitstatus
|
||||||
# of both and returns appropriate errors.
|
# of both and returns appropriate errors.
|
||||||
#
|
#
|
||||||
|
export MOSH_SERVER_PID=$PPID
|
||||||
|
|
||||||
if [ $# -lt 2 ]; then
|
if [ $# -lt 2 ]; then
|
||||||
printf "not enough args\n" >&2
|
printf "not enough args\n" >&2
|
||||||
exit 99
|
exit 99
|
||||||
@@ -12,6 +14,7 @@ fi
|
|||||||
testname=$1
|
testname=$1
|
||||||
shift
|
shift
|
||||||
rm -f $testname.capture $testname.exitstatus
|
rm -f $testname.capture $testname.exitstatus
|
||||||
|
trap ":" TERM HUP QUIT # If the session closes on us, let the test we're running drive.
|
||||||
trap 'rv=$?; echo $rv > $testname.exitstatus; exit $rv' EXIT
|
trap 'rv=$?; echo $rv > $testname.exitstatus; exit $rv' EXIT
|
||||||
# check for tmux
|
# check for tmux
|
||||||
if [ -z "$TMUX_PANE" ]; then
|
if [ -z "$TMUX_PANE" ]; then
|
||||||
|
|||||||
Executable
+114
@@ -0,0 +1,114 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
#
|
||||||
|
# This test checks for operation of the MOSH_SERVER_NETWORK_TIMEOUT variable.
|
||||||
|
# It does this by
|
||||||
|
# * setting the variable
|
||||||
|
# * killing the client (and its network traffic)
|
||||||
|
# * waiting server-side, for the server to die
|
||||||
|
# If it is killed, the test is successful.
|
||||||
|
# If it survives that long and the server is still around, the test fails.
|
||||||
|
# The client waits a bit longer than the server so that status can be collected
|
||||||
|
# properly.
|
||||||
|
#
|
||||||
|
|
||||||
|
TIMEOUT=10
|
||||||
|
|
||||||
|
fail()
|
||||||
|
{
|
||||||
|
printf "$@" 2>&1
|
||||||
|
exit 99
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
PATH=$PATH:.:$srcdir
|
||||||
|
# Top-level wrapper.
|
||||||
|
if [ $# -eq 0 ]; then
|
||||||
|
e2e-test $0 client baseline
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
# OK, we have arguments, we're one of the test hooks.
|
||||||
|
|
||||||
|
client()
|
||||||
|
{
|
||||||
|
case "$myname" in
|
||||||
|
server-network-timeout)
|
||||||
|
export MOSH_SERVER_NETWORK_TMOUT=$TIMEOUT;;
|
||||||
|
server-signal-timeout)
|
||||||
|
export MOSH_SERVER_SIGNAL_TMOUT=$TIMEOUT;;
|
||||||
|
*)
|
||||||
|
fail "unexpected test name %s\n" "$myname"
|
||||||
|
esac
|
||||||
|
shift
|
||||||
|
eval "$@"
|
||||||
|
# The client may be murdered. We need to expect that...
|
||||||
|
retval=$?
|
||||||
|
case $retval in
|
||||||
|
0|1)
|
||||||
|
fail "mosh-client had a normal exit\n";; # test condition failed
|
||||||
|
137)
|
||||||
|
# Aha, signal 9. Wait.
|
||||||
|
sleep $(( $TIMEOUT + 12 ))
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
fail "unknown client wrapper failure, retval=%d\n" $retval
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fail "client wrapper shouldnt get here\n"
|
||||||
|
}
|
||||||
|
baseline()
|
||||||
|
{
|
||||||
|
# check for our wonderful variable
|
||||||
|
if [ -z "$MOSH_SERVER_NETWORK_TMOUT" -a -z "$MOSH_SERVER_SIGNAL_TMOUT" ]; then
|
||||||
|
env
|
||||||
|
fail "Variable unset\n"
|
||||||
|
fi
|
||||||
|
# check for our client
|
||||||
|
if [ -z "$MOSH_CLIENT_PID" ]; then
|
||||||
|
env
|
||||||
|
fail "Client pid unavailable\n"
|
||||||
|
fi
|
||||||
|
if ! kill -0 $MOSH_CLIENT_PID; then
|
||||||
|
fail "mosh client is unexpectedly missing\n"
|
||||||
|
fi
|
||||||
|
# Set up for good return and cleanup on being killed
|
||||||
|
trap "echo got killed >&2; sleep 1; exit 0" SIGHUP SIGTERM
|
||||||
|
sleep 1
|
||||||
|
|
||||||
|
# Kill the client, to stop network traffic.
|
||||||
|
kill -KILL $MOSH_CLIENT_PID
|
||||||
|
case "$myname" in
|
||||||
|
server-network-timeout)
|
||||||
|
# Just wait. This is the hardest part.
|
||||||
|
sleep $(( $TIMEOUT + 7 ))
|
||||||
|
;;
|
||||||
|
server-signal-timeout)
|
||||||
|
# Wait for the timeout to expire.
|
||||||
|
sleep $(( $TIMEOUT + 2 ))
|
||||||
|
# Tell the server to go away.
|
||||||
|
kill -USR1 $MOSH_SERVER_PID
|
||||||
|
sleep 5
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
fail "unexpected test name %s\n" "$myname"
|
||||||
|
esac
|
||||||
|
# If we're still alive and the server is too, the test failed.
|
||||||
|
# XXX the server is getting killed and we're getting here anyway.
|
||||||
|
# Exit with error only if server is still around.
|
||||||
|
! kill -0 $MOSH_SERVER_PID
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
|
||||||
|
myname="$(basename $0 .test)"
|
||||||
|
|
||||||
|
case $1 in
|
||||||
|
baseline|variant)
|
||||||
|
baseline;;
|
||||||
|
client)
|
||||||
|
client "$@";;
|
||||||
|
*)
|
||||||
|
fail "unknown test argument %s\n" $1;;
|
||||||
|
esac
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
server-network-timeout.test
|
||||||
@@ -43,5 +43,4 @@ void Select::handle_signal( int signum )
|
|||||||
|
|
||||||
Select &sel = get_instance();
|
Select &sel = get_instance();
|
||||||
sel.got_signal[ signum ] = 1;
|
sel.got_signal[ signum ] = 1;
|
||||||
sel.got_any_signal = 1;
|
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-7
@@ -58,8 +58,6 @@ public:
|
|||||||
private:
|
private:
|
||||||
Select()
|
Select()
|
||||||
: max_fd( -1 )
|
: max_fd( -1 )
|
||||||
, got_any_signal( 0 )
|
|
||||||
|
|
||||||
/* These initializations are not used; they are just
|
/* These initializations are not used; they are just
|
||||||
here to appease -Weffc++. */
|
here to appease -Weffc++. */
|
||||||
, all_fds( dummy_fd_set )
|
, all_fds( dummy_fd_set )
|
||||||
@@ -124,7 +122,6 @@ public:
|
|||||||
memcpy( &read_fds, &all_fds, sizeof( read_fds ) );
|
memcpy( &read_fds, &all_fds, sizeof( read_fds ) );
|
||||||
memcpy( &error_fds, &all_fds, sizeof( error_fds ) );
|
memcpy( &error_fds, &all_fds, sizeof( error_fds ) );
|
||||||
clear_got_signal();
|
clear_got_signal();
|
||||||
got_any_signal = 0;
|
|
||||||
|
|
||||||
#ifdef HAVE_PSELECT
|
#ifdef HAVE_PSELECT
|
||||||
struct timespec ts;
|
struct timespec ts;
|
||||||
@@ -185,16 +182,25 @@ public:
|
|||||||
return FD_ISSET( fd, &error_fds );
|
return FD_ISSET( fd, &error_fds );
|
||||||
}
|
}
|
||||||
|
|
||||||
bool signal( int signum ) const
|
/* This method consumes a signal notification. */
|
||||||
|
bool signal( int signum )
|
||||||
{
|
{
|
||||||
fatal_assert( signum >= 0 );
|
fatal_assert( signum >= 0 );
|
||||||
fatal_assert( signum <= MAX_SIGNAL_NUMBER );
|
fatal_assert( signum <= MAX_SIGNAL_NUMBER );
|
||||||
return got_signal[ signum ];
|
/* XXX This requires a guard against concurrent signals. */
|
||||||
|
bool rv = got_signal[ signum ];
|
||||||
|
got_signal[ signum ] = 0;
|
||||||
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This method does not consume signal notifications. */
|
||||||
bool any_signal( void ) const
|
bool any_signal( void ) const
|
||||||
{
|
{
|
||||||
return got_any_signal;
|
bool rv = false;
|
||||||
|
for (int i = 0; i < MAX_SIGNAL_NUMBER; i++) {
|
||||||
|
rv |= got_signal[ i ];
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -206,7 +212,6 @@ private:
|
|||||||
|
|
||||||
/* We assume writes to these ints are atomic, though we also try to mask out
|
/* We assume writes to these ints are atomic, though we also try to mask out
|
||||||
concurrent signal handlers. */
|
concurrent signal handlers. */
|
||||||
int got_any_signal;
|
|
||||||
int got_signal[ MAX_SIGNAL_NUMBER + 1 ];
|
int got_signal[ MAX_SIGNAL_NUMBER + 1 ];
|
||||||
|
|
||||||
fd_set all_fds, read_fds, error_fds;
|
fd_set all_fds, read_fds, error_fds;
|
||||||
|
|||||||
Reference in New Issue
Block a user