Added a Signal Handler

In order to prevent the user to ^C while downloading a file (thus,
risking to have an incoherent situation and prevent a bad behaviour of
grive), it's necessary to register some signals. These two classes
provide a wrapper around the C function signal, with facilities to
register and unregister signals..
pull/40/head
Massimo Gengarelli 2012-05-01 19:44:22 +02:00
parent cfca4513e4
commit 95133eff57
5 changed files with 256 additions and 0 deletions

View File

@ -0,0 +1,100 @@
/*
grive: an GPL program to sync a local directory with Google Drive
Copyright (C) 2012 Wan Wai Ho
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation version 2
of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "SignalHandler.hh"
#include <string>
#include <stdexcept>
#include <signal.h>
#include <iostream>
#include <sstream>
namespace gr {
SignalError::SignalError( const std::string& message ) :
std::runtime_error( message )
{
}
SignalError::~SignalError() throw ()
{
}
SignalHandler::SignalHandler()
{
}
SignalHandler::SignalHandler( const SignalHandler& right )
{
}
SignalHandler& SignalHandler::operator ==( const SignalHandler& right )
{
return (*this);
}
SignalHandler::~SignalHandler()
{
}
SignalHandler& SignalHandler::GetInstance()
{
static SignalHandler _instance;
return _instance;
}
void SignalHandler::UnregisterSignal( unsigned int signumber )
{
m_signals[signumber] = 0 ;
// Restore the old signal
signal( ( int ) signumber, m_signalsOld[signumber] );
}
void SignalHandler::RegisterSignal( unsigned int signumber, Callback callback )
{
signals_t::const_iterator anIterator ;
for (anIterator = m_signals.begin(); anIterator != m_signals.end(); ++anIterator)
{
if (anIterator->first == signumber)
{
if (anIterator->second != 0)
{
std::ostringstream oss;
oss << "Signal " << signumber << " already has a callback!";
throw SignalError( oss.str() ); ;
}
}
}
m_signals[signumber] = callback ;
if ( ( m_signalsOld[signumber] = signal( ( int ) signumber, m_signals[signumber] ) ) == SIG_ERR ) {
throw SignalError( " Error while registering the signal! " ) ;
}
}
}

View File

@ -0,0 +1,62 @@
/*
grive: an GPL program to sync a local directory with Google Drive
Copyright (C) 2012 Wan Wai Ho
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation version 2
of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#pragma once
#include <stdexcept>
#include <string>
#include <map>
namespace gr {
class SignalError : public std::runtime_error
{
public :
SignalError( const std::string& message ) ;
virtual ~SignalError() throw () ;
};
class SignalFunctor
{
public :
SignalFunctor() ;
virtual ~SignalFunctor() ;
static void Callback( int signumber ) ;
};
class SignalHandler
{
typedef void (*Callback)(int);
typedef std::map<unsigned int, Callback> signals_t ;
public :
virtual ~SignalHandler() ;
void RegisterSignal ( unsigned int signumber, Callback callback ) ;
void UnregisterSignal( unsigned int signumber );
static SignalHandler& GetInstance() ;
private :
SignalHandler() ;
SignalHandler( const SignalHandler& right ) ;
SignalHandler& operator==( const SignalHandler& right ) ;
signals_t m_signals;
signals_t m_signalsOld;
};
}

View File

@ -22,6 +22,7 @@
#include "util/DateTimeTest.hh"
#include "util/FunctionTest.hh"
#include "util/PathTest.hh"
#include "util/SignalHandlerTest.hh"
int main( int argc, char **argv )
{
@ -31,6 +32,7 @@ int main( int argc, char **argv )
runner.addTest( DateTimeTest::suite( ) ) ;
runner.addTest( FunctionTest::suite( ) ) ;
runner.addTest( PathTest::suite( ) ) ;
runner.addTest( SignalHandlerTest::suite( ) ) ;
runner.run();
return 0 ;

View File

@ -0,0 +1,51 @@
/*
grive: an GPL program to sync a local directory with Google Drive
Copyright (C) 2012 Wan Wai Ho
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation version 2
of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "SignalHandlerTest.hh"
#include "util/SignalHandler.hh"
#include <signal.h>
void test_callback( int )
{
}
namespace grut {
using namespace gr ;
SignalHandlerTest::SignalHandlerTest( )
{
}
void SignalHandlerTest::TestMultipleSignals( )
{
SignalHandler::GetInstance().RegisterSignal( SIGINT, &test_callback );
CPPUNIT_ASSERT_THROW(
SignalHandler::GetInstance().RegisterSignal( SIGINT, &test_callback ),
SignalError);
SignalHandler::GetInstance().UnregisterSignal( SIGINT );
CPPUNIT_ASSERT_NO_THROW(
SignalHandler::GetInstance().RegisterSignal( SIGINT, &test_callback ));
}
}

View File

@ -0,0 +1,41 @@
/*
grive: an GPL program to sync a local directory with Google Drive
Copyright (C) 2012 Wan Wai Ho
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation version 2
of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#pragma once
#include <cppunit/TestFixture.h>
#include <cppunit/extensions/HelperMacros.h>
namespace grut {
class SignalHandlerTest : public CppUnit::TestFixture
{
public :
SignalHandlerTest( ) ;
// declare suit function
CPPUNIT_TEST_SUITE( SignalHandlerTest ) ;
CPPUNIT_TEST( TestMultipleSignals ) ;
CPPUNIT_TEST_SUITE_END();
private :
void TestMultipleSignals( ) ;
} ;
} // end of namespace