From 64c1b28ce211f899ca0fbcae5049532e129f19c1 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Sat, 2 Nov 2013 03:23:17 +0100 Subject: Add some dummy main --- src/main.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 src/main.cpp (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..aeeda34 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,20 @@ +#include +#include + +int main() +{ + Poller p; + // Now I'm the bridge, creating an ircclient because needed. + std::shared_ptr c = std::make_shared(); + p.add_socket_handler(c); + std::shared_ptr d = std::make_shared(); + p.add_socket_handler(d); + std::shared_ptr e = std::make_shared(); + p.add_socket_handler(e); + c->connect("localhost", "7877"); + d->connect("localhost", "7878"); + e->connect("localhost", "7879"); + while (true) + p.poll(); + return 0; +} -- cgit v1.2.3 From 87aaacdb420341bf3619922332d58b95249971bc Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Sun, 3 Nov 2013 00:22:32 +0100 Subject: Rename libirc and libxmpp to irc and xmpp --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index aeeda34..fe3b2e5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,4 +1,4 @@ -#include +#include #include int main() -- cgit v1.2.3 From bf7b05ef72bbdac97704d262ddfe418908267535 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Wed, 6 Nov 2013 20:51:05 +0100 Subject: Implement the Bridge class to translate between the two protocols MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add all useful classes as well: Jid, Iid, IrcChannel, IrcUser etc to properly keep the informations about what we receive from the IRC server. Only handle the MUC join stanza, and send the list of users in the IRC channel to the XMPP user, and the IRC channel’s topic, for now. --- src/main.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index fe3b2e5..b0fb140 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,6 +1,17 @@ #include +#include #include +#include +#include + +#include + +#include +#include + +#include + int main() { Poller p; -- cgit v1.2.3 From ccebe901d7d76dfddc082d994efa54ef2aefee57 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Sat, 9 Nov 2013 06:01:47 +0100 Subject: Check UTF-8 encoding, and convert strings to UTF-8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Handle conversion errors properly by inserting � instead. Add a binary header to provide portable way to write binary literals (I like them) Also add a test file. ref #2404 --- src/main.cpp | 29 +++++++---------------------- 1 file changed, 7 insertions(+), 22 deletions(-) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index b0fb140..b7fa01e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,31 +1,16 @@ -#include -#include #include - -#include -#include +#include #include -#include -#include - -#include - int main() { Poller p; - // Now I'm the bridge, creating an ircclient because needed. - std::shared_ptr c = std::make_shared(); - p.add_socket_handler(c); - std::shared_ptr d = std::make_shared(); - p.add_socket_handler(d); - std::shared_ptr e = std::make_shared(); - p.add_socket_handler(e); - c->connect("localhost", "7877"); - d->connect("localhost", "7878"); - e->connect("localhost", "7879"); - while (true) - p.poll(); + std::shared_ptr xmpp_component = + std::make_shared("irc.localhost", "secret"); + p.add_socket_handler(xmpp_component); + xmpp_component->start(); + while (p.poll()) + ; return 0; } -- cgit v1.2.3 From f0d9273da61ce154dbe460cf58c98de851d30615 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Sun, 10 Nov 2013 20:47:11 +0100 Subject: Add a Config module, and use it to get the password from a file --- src/main.cpp | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index b7fa01e..80c8436 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,13 +1,32 @@ -#include #include +#include +#include +#include #include -int main() +int main(int ac, char** av) { - Poller p; + if (ac > 1) + Config::filename = av[1]; + Config::file_must_exist = true; + + std::string password; + try { // The file must exist + password = Config::get("password", ""); + } + catch (const std::ios::failure& e) { + return 1; + } + if (password.empty()) + { + std::cerr << "No password provided." << std::endl; + return 1; + } std::shared_ptr xmpp_component = - std::make_shared("irc.localhost", "secret"); + std::make_shared("irc.abricot", password); + + Poller p; p.add_socket_handler(xmpp_component); xmpp_component->start(); while (p.poll()) -- cgit v1.2.3 From b60cbda4f93bb83e36b29f5cba975b94b833663d Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Tue, 12 Nov 2013 22:35:27 +0100 Subject: Read the served hostname from the config file --- src/main.cpp | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index 80c8436..71c93f9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -5,26 +5,42 @@ #include #include +/** + * Provide an helpful message to help the user write a minimal working + * configuration file. + */ +int config_help(const std::string& missing_option) +{ + if (!missing_option.empty()) + std::cerr << "Error: empty value for option " << missing_option << "." << std::endl; + std::cerr << + "Please provide a configuration file filled like this:\n\n" + "hostname=irc.example.com\npassword=S3CR3T" + << std::endl; + return 1; +} + int main(int ac, char** av) { if (ac > 1) Config::filename = av[1]; Config::file_must_exist = true; + std::cerr << "Using configuration file: " << Config::filename << std::endl; std::string password; try { // The file must exist password = Config::get("password", ""); } catch (const std::ios::failure& e) { - return 1; + return config_help(""); } + const std::string hostname = Config::get("hostname", ""); if (password.empty()) - { - std::cerr << "No password provided." << std::endl; - return 1; - } + return config_help("hostname"); + if (hostname.empty()) + return config_help("password"); std::shared_ptr xmpp_component = - std::make_shared("irc.abricot", password); + std::make_shared(hostname, password); Poller p; p.add_socket_handler(xmpp_component); -- cgit v1.2.3 From df59a09163bd988ad4da533c4f39de057a3701ba Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Sat, 21 Dec 2013 21:04:46 +0100 Subject: Do not mismatch password and hostname in the config error help message --- src/main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index 71c93f9..2da180b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -36,9 +36,9 @@ int main(int ac, char** av) } const std::string hostname = Config::get("hostname", ""); if (password.empty()) - return config_help("hostname"); - if (hostname.empty()) return config_help("password"); + if (hostname.empty()) + return config_help("hostname"); std::shared_ptr xmpp_component = std::make_shared(hostname, password); -- cgit v1.2.3 From 3afb63a650b8b925ce1ba722dd42b7418f623713 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Sat, 21 Dec 2013 21:04:41 +0100 Subject: Shutdown cleanly on SIGINT --- src/main.cpp | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 50 insertions(+), 3 deletions(-) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index 2da180b..6c9560c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,9 +1,19 @@ #include #include #include +#include #include #include +#include + +#include + +// A flag set by the SIGINT signal handler. +volatile std::atomic stop(false); +// A flag indicating that we are wanting to exit the process. i.e: if this +// flag is set and all connections are closed, we can exit properly. +static bool exiting = false; /** * Provide an helpful message to help the user write a minimal working @@ -20,6 +30,11 @@ int config_help(const std::string& missing_option) return 1; } +static void sigint_handler(int, siginfo_t*, void*) +{ + stop = true; +} + int main(int ac, char** av) { if (ac > 1) @@ -44,8 +59,40 @@ int main(int ac, char** av) Poller p; p.add_socket_handler(xmpp_component); - xmpp_component->start(); - while (p.poll()) - ; + if (!xmpp_component->start()) + { + log_info("Exiting"); + return -1; + } + + // Install the signals used to exit the process cleanly, or reload the + // config + sigset_t mask; + sigemptyset(&mask); + struct sigaction on_sig; + on_sig.sa_sigaction = &sigint_handler; + on_sig.sa_mask = mask; + // we want to catch that signal only once. + // Sending SIGINT again will "force" an exit + on_sig.sa_flags = SA_RESETHAND; + sigaction(SIGINT, &on_sig, nullptr); + sigaction(SIGTERM, &on_sig, nullptr); + + const std::chrono::milliseconds timeout(-1); + while (p.poll(timeout) != -1 || !exiting) + { + if (stop) + { + log_info("Signal received, exiting..."); + exiting = true; + stop = false; + xmpp_component->shutdown(); + } + // If the only existing connection is the one to the XMPP component: + // close the XMPP stream. + if (exiting && p.size() == 1 && xmpp_component->is_document_open()) + xmpp_component->close_document(); + } + log_info("All connection cleanely closed, have a nice day."); return 0; } -- cgit v1.2.3 From e8e592d1ace5413a1e7d8b59b9467c78d8d68ea9 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Fri, 27 Dec 2013 12:01:26 +0100 Subject: Remove disconnected IrcClients --- src/main.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index 6c9560c..28f5a76 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -81,6 +81,9 @@ int main(int ac, char** av) const std::chrono::milliseconds timeout(-1); while (p.poll(timeout) != -1 || !exiting) { + // Check for empty irc_clients (not connected, or with no joined + // channel) and remove them + xmpp_component->clean(); if (stop) { log_info("Signal received, exiting..."); -- cgit v1.2.3 From 8fd2746696d32262b2e6900879a9a315e56f76f2 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Wed, 19 Feb 2014 02:24:00 +0100 Subject: Reload the conf on SIGUSR1/2 --- src/main.cpp | 39 ++++++++++++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 7 deletions(-) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index 28f5a76..b27fd8b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -10,7 +10,9 @@ #include // A flag set by the SIGINT signal handler. -volatile std::atomic stop(false); +static volatile std::atomic stop(false); +// Flag set by the SIGUSR1/2 signal handler. +static volatile std::atomic reload(false); // A flag indicating that we are wanting to exit the process. i.e: if this // flag is set and all connections are closed, we can exit properly. static bool exiting = false; @@ -35,6 +37,11 @@ static void sigint_handler(int, siginfo_t*, void*) stop = true; } +static void sigusr_handler(int, siginfo_t*, void*) +{ + reload = true; +} + int main(int ac, char** av) { if (ac > 1) @@ -69,14 +76,21 @@ int main(int ac, char** av) // config sigset_t mask; sigemptyset(&mask); - struct sigaction on_sig; - on_sig.sa_sigaction = &sigint_handler; - on_sig.sa_mask = mask; + struct sigaction on_sigint; + on_sigint.sa_sigaction = &sigint_handler; + on_sigint.sa_mask = mask; // we want to catch that signal only once. // Sending SIGINT again will "force" an exit - on_sig.sa_flags = SA_RESETHAND; - sigaction(SIGINT, &on_sig, nullptr); - sigaction(SIGTERM, &on_sig, nullptr); + on_sigint.sa_flags = SA_RESETHAND; + sigaction(SIGINT, &on_sigint, nullptr); + sigaction(SIGTERM, &on_sigint, nullptr); + + // Install a signal to reload the config on SIGUSR1/2 + struct sigaction on_sigusr; + on_sigusr.sa_sigaction = &sigusr_handler; + on_sigusr.sa_mask = mask; + sigaction(SIGUSR1, &on_sigusr, nullptr); + sigaction(SIGUSR2, &on_sigusr, nullptr); const std::chrono::milliseconds timeout(-1); while (p.poll(timeout) != -1 || !exiting) @@ -91,6 +105,17 @@ int main(int ac, char** av) stop = false; xmpp_component->shutdown(); } + if (reload) + { + // Closing the config will just force it to be reopened the next time + // a configuration option is needed + log_info("Signal received, reloading the config..."); + Config::close(); + // Destroy the logger instance, to be recreated the next time a log + // line needs to be written + Logger::instance().reset(); + reload = false; + } // If the only existing connection is the one to the XMPP component: // close the XMPP stream. if (exiting && p.size() == 1 && xmpp_component->is_document_open()) -- cgit v1.2.3 From 6804f315464b592eeece8c8837b21c9cd1db074d Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Wed, 19 Feb 2014 02:38:58 +0100 Subject: Set sigaction.sa_flags to 0 --- src/main.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index b27fd8b..43dfe4b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -89,6 +89,7 @@ int main(int ac, char** av) struct sigaction on_sigusr; on_sigusr.sa_sigaction = &sigusr_handler; on_sigusr.sa_mask = mask; + on_sigusr.sa_flags = 0; sigaction(SIGUSR1, &on_sigusr, nullptr); sigaction(SIGUSR2, &on_sigusr, nullptr); -- cgit v1.2.3 From 99aba5667d0d7ba6657f9c175a9342126bc4b0f2 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Sat, 22 Feb 2014 21:42:24 +0100 Subject: Connection to servers does not block the process anymore --- src/main.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index 43dfe4b..9a9543d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -66,11 +66,6 @@ int main(int ac, char** av) Poller p; p.add_socket_handler(xmpp_component); - if (!xmpp_component->start()) - { - log_info("Exiting"); - return -1; - } // Install the signals used to exit the process cleanly, or reload the // config @@ -93,8 +88,10 @@ int main(int ac, char** av) sigaction(SIGUSR1, &on_sigusr, nullptr); sigaction(SIGUSR2, &on_sigusr, nullptr); + xmpp_component->start(); + const std::chrono::milliseconds timeout(-1); - while (p.poll(timeout) != -1 || !exiting) + while (p.poll(timeout) != -1) { // Check for empty irc_clients (not connected, or with no joined // channel) and remove them @@ -119,6 +116,8 @@ int main(int ac, char** av) } // If the only existing connection is the one to the XMPP component: // close the XMPP stream. + if (exiting && xmpp_component->is_connecting()) + xmpp_component->close(); if (exiting && p.size() == 1 && xmpp_component->is_document_open()) xmpp_component->close_document(); } -- cgit v1.2.3 From 5f82c93754037ecbbe8f3632dc3a5f88071415fc Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Mon, 24 Feb 2014 21:02:21 +0100 Subject: Use store() instead of operator=() for std::atomic objects --- src/main.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index 9a9543d..6b24662 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -34,12 +34,12 @@ int config_help(const std::string& missing_option) static void sigint_handler(int, siginfo_t*, void*) { - stop = true; + stop.store(true); } static void sigusr_handler(int, siginfo_t*, void*) { - reload = true; + reload.store(true); } int main(int ac, char** av) @@ -100,7 +100,7 @@ int main(int ac, char** av) { log_info("Signal received, exiting..."); exiting = true; - stop = false; + stop.store(false); xmpp_component->shutdown(); } if (reload) @@ -112,7 +112,7 @@ int main(int ac, char** av) // Destroy the logger instance, to be recreated the next time a log // line needs to be written Logger::instance().reset(); - reload = false; + reload.store(false); } // If the only existing connection is the one to the XMPP component: // close the XMPP stream. -- cgit v1.2.3 From ffc820e234ebba39a0f04607f9a0fb044fe31b73 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Mon, 24 Mar 2014 20:31:02 +0100 Subject: Reconnected immediately to the XMPP whenever it closes the connection --- src/main.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index 6b24662..d40c457 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -114,6 +114,17 @@ int main(int ac, char** av) Logger::instance().reset(); reload.store(false); } + // Reconnect to the XMPP server if this was not intended. This may have + // happened because we sent something invalid to it and it decided to + // close the connection. This is a bug that should be fixed, but we + // still reconnect automatically instead of dropping everything + if (!exiting && !xmpp_component->is_connected() && + !xmpp_component->is_connecting()) + { + xmpp_component->reset(); + p.add_socket_handler(xmpp_component); + xmpp_component->start(); + } // If the only existing connection is the one to the XMPP component: // close the XMPP stream. if (exiting && xmpp_component->is_connecting()) -- cgit v1.2.3 From cdc3183d9eb234feb2e8ca3d3019b78cce73bcf6 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Mon, 24 Mar 2014 20:39:59 +0100 Subject: Introduce two new bool, to know if the xmpp component should try to reconnect If we never succeeded our connection+auth process, means we should probably not attempt any-more, and just give up. If we ever did, this means a reconnect is a good idea --- src/main.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index d40c457..6cba134 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -118,7 +118,8 @@ int main(int ac, char** av) // happened because we sent something invalid to it and it decided to // close the connection. This is a bug that should be fixed, but we // still reconnect automatically instead of dropping everything - if (!exiting && !xmpp_component->is_connected() && + if (!exiting && xmpp_component->ever_auth && + !xmpp_component->is_connected() && !xmpp_component->is_connecting()) { xmpp_component->reset(); -- cgit v1.2.3 From 5507adbe9473f4b41e52d16498f14850773e5e45 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Tue, 27 May 2014 01:01:44 +0200 Subject: SocketHandlers own the poller and add themself into it only when the socket is created MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We want to call socket() with the parameters provided by getaddrinfo, so we can’t addd the fd into the poller immediately. We need to wait the connection attempt, and then the SocketHandler can call add_socket_handler itself, if the connection succeeds, or is in progress. --- src/main.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index 6cba134..40825c9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -61,11 +61,11 @@ int main(int ac, char** av) return config_help("password"); if (hostname.empty()) return config_help("hostname"); - std::shared_ptr xmpp_component = - std::make_shared(hostname, password); - Poller p; - p.add_socket_handler(xmpp_component); + auto p = std::make_shared(); + auto xmpp_component = std::make_shared(p, + hostname, + password); // Install the signals used to exit the process cleanly, or reload the // config @@ -91,7 +91,7 @@ int main(int ac, char** av) xmpp_component->start(); const std::chrono::milliseconds timeout(-1); - while (p.poll(timeout) != -1) + while (p->poll(timeout) != -1) { // Check for empty irc_clients (not connected, or with no joined // channel) and remove them @@ -123,14 +123,13 @@ int main(int ac, char** av) !xmpp_component->is_connecting()) { xmpp_component->reset(); - p.add_socket_handler(xmpp_component); xmpp_component->start(); } // If the only existing connection is the one to the XMPP component: // close the XMPP stream. if (exiting && xmpp_component->is_connecting()) xmpp_component->close(); - if (exiting && p.size() == 1 && xmpp_component->is_document_open()) + if (exiting && p->size() == 1 && xmpp_component->is_document_open()) xmpp_component->close_document(); } log_info("All connection cleanely closed, have a nice day."); -- cgit v1.2.3 From d9d30dd782870b2ab6584fb54b7c19a2a9ae4c78 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Thu, 29 May 2014 01:30:04 +0200 Subject: =?UTF-8?q?Use=20a=20timed=20event=20to=20force=20the=20exit=202?= =?UTF-8?q?=E2=80=AFseconds=20after=20an=20exit=20signal=20is=20received?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix #2469 --- src/main.cpp | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index 40825c9..b5abad9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -17,6 +18,13 @@ static volatile std::atomic reload(false); // flag is set and all connections are closed, we can exit properly. static bool exiting = false; +// The global (and only) TimedEventsManager. It can be accessed by any +// class to add new TimedEvents, and it is used in the main loop to provide +// a timeout to the poller, this way the method execute_expired_events can +// be called on time, without having to do an active “poll” on it every n +// seconds. +TimedEventsManager timed_events; + /** * Provide an helpful message to help the user write a minimal working * configuration file. @@ -32,8 +40,11 @@ int config_help(const std::string& missing_option) return 1; } -static void sigint_handler(int, siginfo_t*, void*) +static void sigint_handler(int sig, siginfo_t*, void*) { + // In 2 seconds, repeat the same signal, to force the exit + timed_events.add_event(TimedEvent(std::chrono::steady_clock::now() + 2s, + [sig]() { raise(sig); })); stop.store(true); } @@ -90,9 +101,10 @@ int main(int ac, char** av) xmpp_component->start(); - const std::chrono::milliseconds timeout(-1); + auto timeout = timed_events.get_timeout(); while (p->poll(timeout) != -1) { + timed_events.execute_expired_events(); // Check for empty irc_clients (not connected, or with no joined // channel) and remove them xmpp_component->clean(); @@ -131,6 +143,7 @@ int main(int ac, char** av) xmpp_component->close(); if (exiting && p->size() == 1 && xmpp_component->is_document_open()) xmpp_component->close_document(); + timeout = timed_events.get_timeout(); } log_info("All connection cleanely closed, have a nice day."); return 0; -- cgit v1.2.3 From 5c9d2c23ba6a401bc9494a6023491bbf3ade8d34 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Fri, 30 May 2014 15:51:43 +0200 Subject: TimedEventsManager is now a singleton --- src/main.cpp | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index b5abad9..2e2f1b2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -18,13 +18,6 @@ static volatile std::atomic reload(false); // flag is set and all connections are closed, we can exit properly. static bool exiting = false; -// The global (and only) TimedEventsManager. It can be accessed by any -// class to add new TimedEvents, and it is used in the main loop to provide -// a timeout to the poller, this way the method execute_expired_events can -// be called on time, without having to do an active “poll” on it every n -// seconds. -TimedEventsManager timed_events; - /** * Provide an helpful message to help the user write a minimal working * configuration file. @@ -43,7 +36,7 @@ int config_help(const std::string& missing_option) static void sigint_handler(int sig, siginfo_t*, void*) { // In 2 seconds, repeat the same signal, to force the exit - timed_events.add_event(TimedEvent(std::chrono::steady_clock::now() + 2s, + TimedEventsManager::instance().add_event(TimedEvent(std::chrono::steady_clock::now() + 2s, [sig]() { raise(sig); })); stop.store(true); } @@ -101,10 +94,10 @@ int main(int ac, char** av) xmpp_component->start(); - auto timeout = timed_events.get_timeout(); + auto timeout = TimedEventsManager::instance().get_timeout(); while (p->poll(timeout) != -1) { - timed_events.execute_expired_events(); + TimedEventsManager::instance().execute_expired_events(); // Check for empty irc_clients (not connected, or with no joined // channel) and remove them xmpp_component->clean(); @@ -143,7 +136,7 @@ int main(int ac, char** av) xmpp_component->close(); if (exiting && p->size() == 1 && xmpp_component->is_document_open()) xmpp_component->close_document(); - timeout = timed_events.get_timeout(); + timeout = TimedEventsManager::instance().get_timeout(); } log_info("All connection cleanely closed, have a nice day."); return 0; -- cgit v1.2.3 From 04d999168ac4629f5e49939f3659b32b2da2563d Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Wed, 2 Jul 2014 03:01:09 +0200 Subject: Add a level of inheritance above SocketHandler SocketHandler has been renamed to TCPSocketHandler SocketHandler is now a simple interface with a few methods, used only by Poller. This way we can inherite from the new SocketHandler class, to handle other types of sockets, and still make them manageable by the poller without any change in the Poller class. --- src/main.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index 2e2f1b2..d9f6a9f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,3 +1,4 @@ +#include #include #include #include -- cgit v1.2.3 From ae469c21ff72966db344af22894d42cf1a1ba58e Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Sat, 21 Feb 2015 05:28:21 +0100 Subject: =?UTF-8?q?Fix=20=E2=80=9Ccleanely=E2=80=9D=20typo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index d9f6a9f..4ed935e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -139,6 +139,6 @@ int main(int ac, char** av) xmpp_component->close_document(); timeout = TimedEventsManager::instance().get_timeout(); } - log_info("All connection cleanely closed, have a nice day."); + log_info("All connection cleanly closed, have a nice day."); return 0; } -- cgit v1.2.3 From 03a8accc464038c6ff206189e2e2824912f2450d Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Sat, 21 Feb 2015 05:30:36 +0100 Subject: =?UTF-8?q?Fix=20=E2=80=9Cconnections=E2=80=9D=20typo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index 4ed935e..393bf05 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -139,6 +139,6 @@ int main(int ac, char** av) xmpp_component->close_document(); timeout = TimedEventsManager::instance().get_timeout(); } - log_info("All connection cleanly closed, have a nice day."); + log_info("All connections cleanly closed, have a nice day."); return 0; } -- cgit v1.2.3 From a50ca30e769a628f609f8cc0eedf5bc10b3f1b5a Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Sat, 21 Feb 2015 06:39:20 +0100 Subject: Use a timer to try reconnecting to the XMPP server only each 2 seconds MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the connection is lost, immediately try to reconnect, then try to reconnect every 2 seconds. This is much better than the previous “Try to re-connect as fast as possible”. --- src/main.cpp | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index 393bf05..a67baf9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -108,6 +108,8 @@ int main(int ac, char** av) exiting = true; stop.store(false); xmpp_component->shutdown(); + // Cancel the timer for an potential reconnection + TimedEventsManager::instance().cancel("XMPP reconnection"); } if (reload) { @@ -127,17 +129,34 @@ int main(int ac, char** av) if (!exiting && xmpp_component->ever_auth && !xmpp_component->is_connected() && !xmpp_component->is_connecting()) - { + { + if (xmpp_component->first_connection_try == true) + { // immediately re-try to connect xmpp_component->reset(); xmpp_component->start(); } + else + { // Re-connecting failed, we now try only each few seconds + auto reconnect_later = [xmpp_component]() + { + xmpp_component->reset(); + xmpp_component->start(); + }; + TimedEvent event(std::chrono::steady_clock::now() + 2s, + reconnect_later, "XMPP reconnection"); + TimedEventsManager::instance().add_event(std::move(event)); + } + } // If the only existing connection is the one to the XMPP component: // close the XMPP stream. if (exiting && xmpp_component->is_connecting()) xmpp_component->close(); if (exiting && p->size() == 1 && xmpp_component->is_document_open()) xmpp_component->close_document(); - timeout = TimedEventsManager::instance().get_timeout(); + if (exiting) // If we are exiting, do not wait for any timed event + timeout = utils::no_timeout; + else + timeout = TimedEventsManager::instance().get_timeout(); } log_info("All connections cleanly closed, have a nice day."); return 0; -- cgit v1.2.3 From b86547dc1ef407ca3838444533bc7145e32a0d90 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Wed, 9 Jul 2014 13:02:37 +0200 Subject: Implement async DNS resolution using c-ares fix #2533 --- src/main.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index a67baf9..94c3cb5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,4 +1,3 @@ -#include #include #include #include @@ -11,6 +10,10 @@ #include +#ifdef CARES_FOUND +# include +#endif + // A flag set by the SIGINT signal handler. static volatile std::atomic stop(false); // Flag set by the SIGUSR1/2 signal handler. @@ -95,6 +98,10 @@ int main(int ac, char** av) xmpp_component->start(); + +#ifdef CARES_FOUND + DNSHandler::instance.watch_dns_sockets(p); +#endif auto timeout = TimedEventsManager::instance().get_timeout(); while (p->poll(timeout) != -1) { @@ -108,6 +115,9 @@ int main(int ac, char** av) exiting = true; stop.store(false); xmpp_component->shutdown(); +#ifdef CARES_FOUND + DNSHandler::instance.destroy(); +#endif // Cancel the timer for an potential reconnection TimedEventsManager::instance().cancel("XMPP reconnection"); } @@ -153,6 +163,10 @@ int main(int ac, char** av) xmpp_component->close(); if (exiting && p->size() == 1 && xmpp_component->is_document_open()) xmpp_component->close_document(); +#ifdef CARES_FOUND + if (!exiting) + DNSHandler::instance.watch_dns_sockets(p); +#endif if (exiting) // If we are exiting, do not wait for any timed event timeout = utils::no_timeout; else -- cgit v1.2.3 From 7115aa3b7f22f95e5e614ffc74c467844c08d965 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Tue, 24 Feb 2015 16:28:30 +0100 Subject: Add a reload add-hoc command --- src/main.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index 94c3cb5..148412e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -123,13 +124,8 @@ int main(int ac, char** av) } if (reload) { - // Closing the config will just force it to be reopened the next time - // a configuration option is needed log_info("Signal received, reloading the config..."); - Config::close(); - // Destroy the logger instance, to be recreated the next time a log - // line needs to be written - Logger::instance().reset(); + ::reload_process(); reload.store(false); } // Reconnect to the XMPP server if this was not intended. This may have -- cgit v1.2.3 From d600a2843f1dbe3b1ba2dead9a020cc73d7d10ae Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Fri, 27 Feb 2015 12:16:09 +0100 Subject: Remove all the libs that are now in louloulibs --- src/main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index 148412e..9042a57 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include #include @@ -72,7 +72,7 @@ int main(int ac, char** av) return config_help("hostname"); auto p = std::make_shared(); - auto xmpp_component = std::make_shared(p, + auto xmpp_component = std::make_shared(p, hostname, password); -- cgit v1.2.3 From 33cdc6010e9c19b6a74c65171c0557f0f2855f4c Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Wed, 4 Mar 2015 05:56:08 +0100 Subject: Set the default value to biboumi.cfg --- src/main.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index 9042a57..98013eb 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -55,6 +55,9 @@ int main(int ac, char** av) { if (ac > 1) Config::filename = av[1]; + else + Config::filename = "biboumi.cfg"; + Config::file_must_exist = true; std::cerr << "Using configuration file: " << Config::filename << std::endl; -- cgit v1.2.3 From d5324ac7780e9a6297631a9c3dc83676e0c1d246 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Mon, 13 Apr 2015 01:53:53 +0200 Subject: Re-order a few things in main.cpp --- src/main.cpp | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index 98013eb..cc73244 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -74,11 +74,6 @@ int main(int ac, char** av) if (hostname.empty()) return config_help("hostname"); - auto p = std::make_shared(); - auto xmpp_component = std::make_shared(p, - hostname, - password); - // Install the signals used to exit the process cleanly, or reload the // config sigset_t mask; @@ -100,9 +95,11 @@ int main(int ac, char** av) sigaction(SIGUSR1, &on_sigusr, nullptr); sigaction(SIGUSR2, &on_sigusr, nullptr); + auto p = std::make_shared(); + auto xmpp_component = + std::make_shared(p, hostname, password); xmpp_component->start(); - #ifdef CARES_FOUND DNSHandler::instance.watch_dns_sockets(p); #endif @@ -119,10 +116,7 @@ int main(int ac, char** av) exiting = true; stop.store(false); xmpp_component->shutdown(); -#ifdef CARES_FOUND - DNSHandler::instance.destroy(); -#endif - // Cancel the timer for an potential reconnection + // Cancel the timer for a potential reconnection TimedEventsManager::instance().cancel("XMPP reconnection"); } if (reload) @@ -171,6 +165,9 @@ int main(int ac, char** av) else timeout = TimedEventsManager::instance().get_timeout(); } +#ifdef CARES_FOUND + DNSHandler::instance.destroy(); +#endif log_info("All connections cleanly closed, have a nice day."); return 0; } -- cgit v1.2.3 From 6a28bde1dd21809b3c1202aab0b695b11f4d4846 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Mon, 20 Apr 2015 23:58:05 +0200 Subject: Reset the signal handlers when SIGINT or SIGTERM is received To avoid doing a double exit when receiving bot SIGINT and SIGTERM --- src/main.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index cc73244..62a28a5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -40,6 +40,18 @@ int config_help(const std::string& missing_option) static void sigint_handler(int sig, siginfo_t*, void*) { + // We reset the SIGTERM or SIGINT (the one that didn't trigger this + // handler) signal handler to its default value. This avoid calling this + // handler twice, if the process receive both signals in a quick + // succession. + int sig_to_reset = (sig == SIGINT? SIGTERM: SIGINT); + sigset_t mask; + sigemptyset(&mask); + struct sigaction sigreset = {}; + sigreset.sa_handler = SIG_DFL; + sigreset.sa_mask = mask; + sigaction(sig_to_reset, &sigreset, nullptr); + // In 2 seconds, repeat the same signal, to force the exit TimedEventsManager::instance().add_event(TimedEvent(std::chrono::steady_clock::now() + 2s, [sig]() { raise(sig); })); -- cgit v1.2.3 From ac30733800b69dcb1589adcba6a42b20fa763e8f Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Thu, 30 Apr 2015 09:56:13 +0200 Subject: Search for the config file in $XDG_CONFIG_DIR/biboumi. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This environment variable points to the location the user expects to find every program’s config file, or if it isn’t set, ~/.config/biboumi (with a fallback to . if $HOME isn’t set). fix #2553 --- src/main.cpp | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index 62a28a5..80462cb 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include @@ -68,7 +69,19 @@ int main(int ac, char** av) if (ac > 1) Config::filename = av[1]; else - Config::filename = "biboumi.cfg"; + { + const char* xdg_config_home = getenv("XDG_CONFIG_HOME"); + if (xdg_config_home) + Config::filename = std::string{xdg_config_home} + "/" "biboumi" "/" "biboumi.cfg"; + else + { + const char* home = getenv("HOME"); + if (home) + Config::filename = std::string{home} + "/" ".config" "/" "biboumi" "/" "biboumi.cfg"; + else + Config::filename = "biboumi.cfg"; + } + } Config::file_must_exist = true; std::cerr << "Using configuration file: " << Config::filename << std::endl; -- cgit v1.2.3 From e24ed4f70c22142029fa8e6cf5b874e8bc261bc3 Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Mon, 4 May 2015 17:08:08 +0200 Subject: Make sure XDG_CONFIG_HOME is absolute, as per XDG basedir spec. --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index 80462cb..4a207b9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -71,7 +71,7 @@ int main(int ac, char** av) else { const char* xdg_config_home = getenv("XDG_CONFIG_HOME"); - if (xdg_config_home) + if (xdg_config_home && xdg_config_home[0] == '/') Config::filename = std::string{xdg_config_home} + "/" "biboumi" "/" "biboumi.cfg"; else { -- cgit v1.2.3 From 897b281e67dc82700db9fd9c2dedc5e01e5871ee Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Wed, 27 May 2015 23:44:23 +0200 Subject: Avoid some potential race conditions by blocking the signals we manage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit They are atomically unblocked in the ppoll/epoll_pwait calls, avoiding any race condition on the check of the “stop” or “reload” booleans. --- src/main.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index 4a207b9..adc0c7c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -99,9 +99,19 @@ int main(int ac, char** av) if (hostname.empty()) return config_help("hostname"); + // Block the signals we want to manage. They will be unblocked only during + // the epoll_pwait or ppoll calls. This avoids some race conditions, + // explained in man 2 pselect on linux + sigset_t mask; + sigemptyset(&mask); + sigaddset(&mask, SIGINT); + sigaddset(&mask, SIGTERM); + sigaddset(&mask, SIGUSR1); + sigaddset(&mask, SIGUSR2); + sigprocmask(SIG_BLOCK, &mask, nullptr); + // Install the signals used to exit the process cleanly, or reload the // config - sigset_t mask; sigemptyset(&mask); struct sigaction on_sigint; on_sigint.sa_sigaction = &sigint_handler; -- cgit v1.2.3 From 810ea19fe32c64a93bbe15b9b10541259bcc9321 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Wed, 10 Jun 2015 16:47:13 +0200 Subject: Exit with 1 if the connection to the XMPP server fails This helps the system understand if the process started correctly or not, when systemd is not used fix #3078 --- src/main.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index adc0c7c..159dcbe 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -203,6 +203,8 @@ int main(int ac, char** av) #ifdef CARES_FOUND DNSHandler::instance.destroy(); #endif + if (!xmpp_component->ever_auth) + return 1; // To signal that the process did not properly start log_info("All connections cleanly closed, have a nice day."); return 0; } -- cgit v1.2.3 From ea0b2f2bb871e7760d1936bb9b193655682df413 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Fri, 18 Sep 2015 09:18:33 +0200 Subject: Create a xdg_path function --- src/main.cpp | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index 159dcbe..5c9e071 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4,11 +4,11 @@ #include #include #include +#include #include #include #include -#include #include @@ -69,19 +69,7 @@ int main(int ac, char** av) if (ac > 1) Config::filename = av[1]; else - { - const char* xdg_config_home = getenv("XDG_CONFIG_HOME"); - if (xdg_config_home && xdg_config_home[0] == '/') - Config::filename = std::string{xdg_config_home} + "/" "biboumi" "/" "biboumi.cfg"; - else - { - const char* home = getenv("HOME"); - if (home) - Config::filename = std::string{home} + "/" ".config" "/" "biboumi" "/" "biboumi.cfg"; - else - Config::filename = "biboumi.cfg"; - } - } + Config::filename = xdg_path("biboumi.cfg"); Config::file_must_exist = true; std::cerr << "Using configuration file: " << Config::filename << std::endl; -- cgit v1.2.3 From 33fa1dcd5a87035de1d9b8df65e5c7551b4bbd1b Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Fri, 18 Sep 2015 09:39:49 +0200 Subject: Also a xdg_data_path --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index 5c9e071..a160df9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -69,7 +69,7 @@ int main(int ac, char** av) if (ac > 1) Config::filename = av[1]; else - Config::filename = xdg_path("biboumi.cfg"); + Config::filename = xdg_config_path("biboumi.cfg"); Config::file_must_exist = true; std::cerr << "Using configuration file: " << Config::filename << std::endl; -- cgit v1.2.3 From 9167cdf1269c1956b72db1e8dfdbfd61cbf66bb9 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Tue, 22 Dec 2015 17:34:33 +0100 Subject: Notify systemd when the process is stopping --- src/main.cpp | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index a160df9..226b400 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -16,6 +16,10 @@ # include #endif +#ifdef SYSTEMD_FOUND +# include +#endif + // A flag set by the SIGINT signal handler. static volatile std::atomic stop(false); // Flag set by the SIGUSR1/2 signal handler. @@ -136,6 +140,9 @@ int main(int ac, char** av) if (stop) { log_info("Signal received, exiting..."); +#ifdef SYSTEMD_FOUND + sd_notify(0, "STOPPING=1"); +#endif exiting = true; stop.store(false); xmpp_component->shutdown(); -- cgit v1.2.3 From 46ff73662cc94220c5ee962b591c8ee327de6f85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Tue, 14 Jun 2016 03:02:36 +0200 Subject: Clean the Config module, use static things instead of a stupid singleton --- src/main.cpp | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index 226b400..cbec4a6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -47,7 +47,7 @@ static void sigint_handler(int sig, siginfo_t*, void*) { // We reset the SIGTERM or SIGINT (the one that didn't trigger this // handler) signal handler to its default value. This avoid calling this - // handler twice, if the process receive both signals in a quick + // handler twice, if the process receives both signals in a quick // succession. int sig_to_reset = (sig == SIGINT? SIGTERM: SIGINT); sigset_t mask; @@ -70,24 +70,16 @@ static void sigusr_handler(int, siginfo_t*, void*) int main(int ac, char** av) { - if (ac > 1) - Config::filename = av[1]; - else - Config::filename = xdg_config_path("biboumi.cfg"); + const std::string conf_filename = ac > 1 ? av[1] : xdg_config_path("biboumi.cfg"); + std::cerr << "Using configuration file: " << conf_filename << std::endl; - Config::file_must_exist = true; - std::cerr << "Using configuration file: " << Config::filename << std::endl; - - std::string password; - try { // The file must exist - password = Config::get("password", ""); - } - catch (const std::ios::failure& e) { + if (!Config::read_conf(conf_filename)) return config_help(""); - } - const std::string hostname = Config::get("hostname", ""); + + const std::string password = Config::get("password", ""); if (password.empty()) return config_help("password"); + const std::string hostname = Config::get("hostname", ""); if (hostname.empty()) return config_help("hostname"); -- cgit v1.2.3 From e8671042f792d8d967e476ea01821243c3465412 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Tue, 14 Jun 2016 03:21:15 +0200 Subject: Improve the signal handling by disabling them while an handler is running --- src/main.cpp | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index cbec4a6..ed05d36 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -45,18 +45,6 @@ int config_help(const std::string& missing_option) static void sigint_handler(int sig, siginfo_t*, void*) { - // We reset the SIGTERM or SIGINT (the one that didn't trigger this - // handler) signal handler to its default value. This avoid calling this - // handler twice, if the process receives both signals in a quick - // succession. - int sig_to_reset = (sig == SIGINT? SIGTERM: SIGINT); - sigset_t mask; - sigemptyset(&mask); - struct sigaction sigreset = {}; - sigreset.sa_handler = SIG_DFL; - sigreset.sa_mask = mask; - sigaction(sig_to_reset, &sigreset, nullptr); - // In 2 seconds, repeat the same signal, to force the exit TimedEventsManager::instance().add_event(TimedEvent(std::chrono::steady_clock::now() + 2s, [sig]() { raise(sig); })); @@ -96,10 +84,10 @@ int main(int ac, char** av) // Install the signals used to exit the process cleanly, or reload the // config - sigemptyset(&mask); struct sigaction on_sigint; on_sigint.sa_sigaction = &sigint_handler; - on_sigint.sa_mask = mask; + // All signals must be blocked while a signal handler is running + sigfillset(&on_sigint.sa_mask); // we want to catch that signal only once. // Sending SIGINT again will "force" an exit on_sigint.sa_flags = SA_RESETHAND; @@ -109,7 +97,7 @@ int main(int ac, char** av) // Install a signal to reload the config on SIGUSR1/2 struct sigaction on_sigusr; on_sigusr.sa_sigaction = &sigusr_handler; - on_sigusr.sa_mask = mask; + sigfillset(&on_sigusr.sa_mask); on_sigusr.sa_flags = 0; sigaction(SIGUSR1, &on_sigusr, nullptr); sigaction(SIGUSR2, &on_sigusr, nullptr); -- cgit v1.2.3 From 4c1b9abe7e230a39b119bdc45ebcd5e677fad488 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Tue, 12 Jul 2016 00:31:57 +0200 Subject: Properly catch and handle database errors Do not use a singleton for the database. fix #3203 --- src/main.cpp | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index ed05d36..422219a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3,22 +3,15 @@ #include #include #include -#include #include - -#include -#include -#include - -#include +#include #ifdef CARES_FOUND # include #endif -#ifdef SYSTEMD_FOUND -# include -#endif +#include +#include // A flag set by the SIGINT signal handler. static volatile std::atomic stop(false); @@ -71,6 +64,12 @@ int main(int ac, char** av) if (hostname.empty()) return config_help("hostname"); + try { + open_database(); + } catch (...) { + return 1; + } + // Block the signals we want to manage. They will be unblocked only during // the epoll_pwait or ppoll calls. This avoids some race conditions, // explained in man 2 pselect on linux -- cgit v1.2.3 From db503b23e86d1cb390d12298875eb0eaffdbfa3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Sun, 24 Jul 2016 19:41:01 +0200 Subject: Use log_error instead of cerr --- src/main.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index 422219a..8542e41 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -28,11 +28,9 @@ static bool exiting = false; int config_help(const std::string& missing_option) { if (!missing_option.empty()) - std::cerr << "Error: empty value for option " << missing_option << "." << std::endl; - std::cerr << - "Please provide a configuration file filled like this:\n\n" - "hostname=irc.example.com\npassword=S3CR3T" - << std::endl; + log_error("Error: empty value for option ", missing_option, "."); + log_error("Please provide a configuration file filled like this:\n\n" + "hostname=irc.example.com\npassword=S3CR3T"); return 1; } @@ -52,7 +50,7 @@ static void sigusr_handler(int, siginfo_t*, void*) int main(int ac, char** av) { const std::string conf_filename = ac > 1 ? av[1] : xdg_config_path("biboumi.cfg"); - std::cerr << "Using configuration file: " << conf_filename << std::endl; + log_info("Using configuration file: ", conf_filename); if (!Config::read_conf(conf_filename)) return config_help(""); -- cgit v1.2.3 From 085a48ea48b9fcb2188b645d2a373d97b8dab9aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Thu, 28 Jul 2016 11:56:33 +0200 Subject: Do not use the logger before the configuration has been loaded first --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index 8542e41..9b36880 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -50,7 +50,7 @@ static void sigusr_handler(int, siginfo_t*, void*) int main(int ac, char** av) { const std::string conf_filename = ac > 1 ? av[1] : xdg_config_path("biboumi.cfg"); - log_info("Using configuration file: ", conf_filename); + std::cout << "Using configuration file: " << conf_filename << std::endl; if (!Config::read_conf(conf_filename)) return config_help(""); -- cgit v1.2.3 From f89361c3701ef66e17a7d8159d99e3d0b0c76e4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Sun, 31 Jul 2016 18:03:33 +0200 Subject: Provide a --help option fix #3183 --- src/main.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index 9b36880..905cfa6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -34,6 +34,12 @@ int config_help(const std::string& missing_option) return 1; } +int display_help() +{ + std::cout << "Usage: biboumi [configuration_file]" << std::endl; + return 0; +} + static void sigint_handler(int sig, siginfo_t*, void*) { // In 2 seconds, repeat the same signal, to force the exit @@ -49,6 +55,20 @@ static void sigusr_handler(int, siginfo_t*, void*) int main(int ac, char** av) { + if (ac > 1) + { + const std::string arg = av[1]; + if (arg.size() >= 2 && arg[0] == '-' && arg[1] == '-') + { + if (arg == "--help") + return display_help(); + else + { + std::cerr << "Unknow command line option: " << arg << std::endl; + return 1; + } + } + } const std::string conf_filename = ac > 1 ? av[1] : xdg_config_path("biboumi.cfg"); std::cout << "Using configuration file: " << conf_filename << std::endl; -- cgit v1.2.3 From 58000c36a64fd8d4b8cdb7d76f318fca5a81381e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Mon, 1 Aug 2016 09:48:45 +0200 Subject: Rephrase an error message --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index 905cfa6..53f3193 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -28,7 +28,7 @@ static bool exiting = false; int config_help(const std::string& missing_option) { if (!missing_option.empty()) - log_error("Error: empty value for option ", missing_option, "."); + log_error("Configuration error: empty value for option ", missing_option, "."); log_error("Please provide a configuration file filled like this:\n\n" "hostname=irc.example.com\npassword=S3CR3T"); return 1; -- cgit v1.2.3