Skip to content

Commit

Permalink
fixup! add control-c-handler to rsutils
Browse files Browse the repository at this point in the history
  • Loading branch information
maloel committed Jan 5, 2025
1 parent cb48695 commit 602fc76
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 76 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,24 @@ namespace rsutils {
namespace concurrency {


// A Python Event-like implementation, simplifying condition-variable and mutex access
// A handler for catching Control-C input from the user
//
// NOTE: only a single instance should be in use: using more than one has undefined behavior
//
class control_c_handler
{
public:
control_c_handler();
~control_c_handler();

// Return true if a Control-C happened
bool was_pressed() const;

// Make was_pressed() return false
void reset();

// Block until a Control-C happens
// If already was_pressed(), the state is cleared and a new Control-C is waited on
void wait();
};

Expand Down
161 changes: 86 additions & 75 deletions third-party/rsutils/src/control-c-handler.cpp
Original file line number Diff line number Diff line change
@@ -1,75 +1,86 @@
// License: Apache 2.0. See LICENSE file in root directory.
// Copyright(c) 2024 Intel Corporation. All Rights Reserved.
#include <rsutils/concurrency/control-c-handler.h>
#include <rsutils/concurrency/event.h>
#include <rsutils/easylogging/easyloggingpp.h>

#include <signal.h>


namespace rsutils {
namespace concurrency {


namespace {

event sigint_ev;


void handle_signal( int signal )
{
switch( signal )
{
case SIGINT:
sigint_ev.set();
break;
}
}

} // namespace


control_c_handler::control_c_handler()
{
#ifdef _WIN32
signal( SIGINT, handle_signal );
#else
struct sigaction sa;
sa.sa_handler = &handle_signal;
sa.sa_flags = SA_RESTART;
sigfillset( &sa.sa_mask );
if( sigaction( SIGINT, &sa, NULL ) == -1 )
LOG_ERROR( "Cannot install SIGINT handler" );
#endif
}


control_c_handler::~control_c_handler()
{
#ifdef _WIN32
signal( SIGINT, SIG_DFL );
#else
struct sigaction sa;
sa.sa_handler = SIG_DFL;
sa.sa_flags = SA_RESTART;
sigfillset( &sa.sa_mask );
if( sigaction( SIGINT, &sa, NULL ) == -1 )
LOG_DEBUG( "cannot uninstall SIGINT handler" );
#endif
}


bool control_c_handler::was_pressed() const
{
return sigint_ev.is_set();
}


void control_c_handler::wait()
{
sigint_ev.clear_and_wait();
}


} // namespace concurrency
} // namespace rsutils
// License: Apache 2.0. See LICENSE file in root directory.
// Copyright(c) 2024 Intel Corporation. All Rights Reserved.
#include <rsutils/concurrency/control-c-handler.h>
#include <rsutils/concurrency/event.h>
#include <rsutils/easylogging/easyloggingpp.h>

#include <signal.h>
#include <atomic>


namespace rsutils {
namespace concurrency {


namespace {

event sigint_ev;
std::atomic_bool in_use( false );


void handle_signal( int signal )
{
switch( signal )
{
case SIGINT:
sigint_ev.set();
break;
}
}

} // namespace


control_c_handler::control_c_handler()
{
if( in_use.exchange( true ) )
throw std::runtime_error( "a Control-C handler is already in effect" );
#ifdef _WIN32
signal( SIGINT, handle_signal );
#else
struct sigaction sa;
sa.sa_handler = &handle_signal;
sa.sa_flags = SA_RESTART;
sigfillset( &sa.sa_mask );
if( sigaction( SIGINT, &sa, NULL ) == -1 )
LOG_ERROR( "Cannot install SIGINT handler" );
#endif
}


control_c_handler::~control_c_handler()
{
#ifdef _WIN32
signal( SIGINT, SIG_DFL );
#else
struct sigaction sa;
sa.sa_handler = SIG_DFL;
sa.sa_flags = SA_RESTART;
sigfillset( &sa.sa_mask );
if( sigaction( SIGINT, &sa, NULL ) == -1 )
LOG_DEBUG( "cannot uninstall SIGINT handler" );
#endif
in_use = false;
}


bool control_c_handler::was_pressed() const
{
return sigint_ev.is_set();
}


void control_c_handler::reset()
{
sigint_ev.clear();
}


void control_c_handler::wait()
{
sigint_ev.clear_and_wait();
}


} // namespace concurrency
} // namespace rsutils

0 comments on commit 602fc76

Please sign in to comment.