From 85c46a0fcce3495fe94397d53791628a8ccc74c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be> Date: Fri, 17 Jan 2014 21:02:19 +0100 Subject: Sluift: Allow blocking calls to be interrupted. Change-Id: I3755e796fbddc038022bbf543c7b1c0529a9b0f9 diff --git a/Sluift/Examples/Login.lua b/Sluift/Examples/Login.lua index c43b72a..fadb651 100644 --- a/Sluift/Examples/Login.lua +++ b/Sluift/Examples/Login.lua @@ -1,5 +1,5 @@ --[[ - Copyright (c) 2010-2013 Remko Tronçon + Copyright (c) 2010-2014 Remko Tronçon Licensed under the GNU General Public License v3. See Documentation/Licenses/GPLv3.txt for more information. --]] @@ -21,7 +21,7 @@ sluift.debug = os.getenv("SLUIFT_DEBUG") or false print("Connecting " .. os.getenv("SLUIFT_JID") .. " ...") c = sluift.new_client(os.getenv("SLUIFT_JID"), os.getenv("SLUIFT_PASS")) -c:set_options({compress = false, tls = false}) +c:set_options{compress = false, tls = false} c:connect() c:send_presence("") diff --git a/Sluift/SConscript b/Sluift/SConscript index d88e948..38baef1 100644 --- a/Sluift/SConscript +++ b/Sluift/SConscript @@ -32,6 +32,7 @@ elif env["SCONS_STAGE"] == "build" : "ElementConvertors/CommandConvertor.cpp", "ClientHelpers.cpp", "SluiftClient.cpp", + "Watchdog.cpp", "core.c", "client.cpp", "sluift.cpp" diff --git a/Sluift/SluiftGlobals.h b/Sluift/SluiftGlobals.h index 18a90c2..0d8e637 100644 --- a/Sluift/SluiftGlobals.h +++ b/Sluift/SluiftGlobals.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013 Remko Tronçon + * Copyright (c) 2013-2014 Remko Tronçon * Licensed under the GNU General Public License. * See the COPYING file for more information. */ @@ -9,10 +9,11 @@ #include <Sluift/LuaElementConvertors.h> #include <Swiften/EventLoop/SimpleEventLoop.h> #include <Swiften/Network/BoostNetworkFactories.h> +#include <signal.h> namespace Swift { struct SluiftGlobals { - SluiftGlobals() : networkFactories(&eventLoop) {} + SluiftGlobals() : networkFactories(&eventLoop), interruptRequested(0) {} int timeout; bool debug; @@ -20,5 +21,6 @@ namespace Swift { SimpleEventLoop eventLoop; BoostNetworkFactories networkFactories; int coreLibIndex; + sig_atomic_t interruptRequested; }; } diff --git a/Sluift/Watchdog.cpp b/Sluift/Watchdog.cpp new file mode 100644 index 0000000..8b1c9ab --- /dev/null +++ b/Sluift/Watchdog.cpp @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2014 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Sluift/Watchdog.h> + +#include <Sluift/globals.h> + +static const int INTERVAL_MS = 500; + + +using namespace Swift; + +Watchdog::Watchdog(int timeout, TimerFactory* timerFactory) : + remainingTime(timeout), + timerFactory(timerFactory), + timedOut(false) { + Sluift::globals.interruptRequested = 0; + + int nextTimeout = remainingTime >= 0 ? std::min(remainingTime, INTERVAL_MS) : INTERVAL_MS; + + timer = timerFactory->createTimer(nextTimeout); + timer->onTick.connect(boost::bind(&Watchdog::handleTimerTick, this)); + remainingTime -= nextTimeout; + timer->start(); +} + +Watchdog::~Watchdog() { + if (timer) { + timer->stop(); + } +} + +void Watchdog::handleTimerTick() { + if (Sluift::globals.interruptRequested || remainingTime == 0) { + timedOut = true; + } + else { + int nextTimeout = remainingTime >= 0 ? std::min(remainingTime, INTERVAL_MS) : INTERVAL_MS; + if (nextTimeout != INTERVAL_MS) { + timer->onTick.disconnect(boost::bind(&Watchdog::handleTimerTick, this)); + timer = timerFactory->createTimer(nextTimeout); + timer->onTick.connect(boost::bind(&Watchdog::handleTimerTick, this)); + } + remainingTime -= nextTimeout; + timer->start(); + } +} diff --git a/Sluift/Watchdog.h b/Sluift/Watchdog.h index 95b6971..868621e 100644 --- a/Sluift/Watchdog.h +++ b/Sluift/Watchdog.h @@ -1,44 +1,32 @@ /* - * Copyright (c) 2011 Remko Tronçon + * Copyright (c) 2011-2014 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ #pragma once +#include <algorithm> + #include <Swiften/Network/TimerFactory.h> namespace Swift { class Watchdog { public: - Watchdog(int timeout, TimerFactory* timerFactory) : timedOut(false) { - if (timeout > 0) { - timer = timerFactory->createTimer(timeout); - timer->start(); - timer->onTick.connect(boost::bind(&Watchdog::handleTimerTick, this)); - } - else if (timeout == 0) { - timedOut = true; - } - } - - ~Watchdog() { - if (timer) { - timer->stop(); - } - } + Watchdog(int timeout, TimerFactory* timerFactory); + ~Watchdog(); bool getTimedOut() const { return timedOut; } private: - void handleTimerTick() { - timedOut = true; - } + void handleTimerTick(); private: Timer::ref timer; + int remainingTime; + TimerFactory* timerFactory; bool timedOut; }; } diff --git a/Sluift/client.cpp b/Sluift/client.cpp index 16f1281..9cb5090 100644 --- a/Sluift/client.cpp +++ b/Sluift/client.cpp @@ -25,7 +25,6 @@ #include <Swiften/Roster/SetRosterRequest.h> #include <Swiften/Presence/SubscriptionManager.h> #include <Swiften/Roster/XMPPRosterItem.h> -#include <Sluift/Watchdog.h> #include <Swiften/Queries/Requests/GetSoftwareVersionRequest.h> #include <Sluift/Lua/FunctionRegistration.h> #include <Swiften/Base/foreach.h> diff --git a/Sluift/main.cpp b/Sluift/main.cpp index 76ba572..505cc5c 100644 --- a/Sluift/main.cpp +++ b/Sluift/main.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013 Remko Tronçon + * Copyright (c) 2013-2014 Remko Tronçon * Licensed under the GNU General Public License. * See the COPYING file for more information. */ @@ -15,6 +15,7 @@ #include <boost/version.hpp> #include <boost/numeric/conversion/cast.hpp> #include <boost/assign/list_of.hpp> +#include <Sluift/globals.h> #include <Sluift/Console.h> #include <Sluift/StandardTerminal.h> #include <Sluift/sluift.h> @@ -48,6 +49,10 @@ static const luaL_Reg defaultLibraries[] = { {NULL, NULL} }; +static void handleInterruptSignal(int) { + Sluift::globals.interruptRequested = 1; +} + static void checkResult(lua_State* L, int result) { if (result && !lua_isnil(L, -1)) { const char* errorMessage = lua_tostring(L, -1); @@ -150,6 +155,9 @@ int main(int argc, char* argv[]) { // Run console if (arguments.count("interactive") || arguments.count("script") == 0) { + // Set up signal handler + signal(SIGINT, handleInterruptSignal); + // Import some useful functions into the global namespace lua_getglobal(L, "sluift"); std::vector<std::string> globalImports = boost::assign::list_of -- cgit v0.10.2-6-g49f6