-
-
Notifications
You must be signed in to change notification settings - Fork 349
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Can't stop a running instance of a class that uses CrowCpp #835
Comments
Maybe it works if App::signal_add (int signal_number) will be called for SIGINT and SIGHUP? |
It now looks like |
Its signal_add hmm, maybe it does not work. |
My POC code has some issues but the basic issue remains. I remade it and added a compile time flag. Like so: Sign of life from main thread ... If you set it to true it'll start crow and then the issue appears. Edit: that formatting is really weird... `#include std::atomic_bool basicTest = true; // Compile time flag. Set to false to test crow. std::atomic_bool keepOnRunning = true; // Main program loop control. class Worker {
private: void signalHandler(int signum) { int main() {
} |
This version works for SIGHUP but not for SIGINT -> #include std::atomic_bool basicTest = false; // Compile time flag. Set to false to test crow. class Worker {
private: void signalHandler(int signum) { int main() {
} Sending kill -SIGHUP 16645 stops it as it should -> PID 16645 Sending kill -SIGINT 16666 just immediately stops Crow but the application doesn't see the signal? PID 16666 kill -9 16666 -> Killed It seems that Crow is intercepting the SIGINT signal and not allowing it to propagate to the rest of the application? I tried using using a signal relay mechanism within the application to no avail. The issue stays. #include std::atomic_bool basicTest = false; // Compile time flag. Set to false to test crow. class Worker {
private: void relaySignalHandler(int signum) { void signalHandler(int signum) { int main() {
} So I basically can never interrupt the program whilst SIGHUP and likely other do work correctly. |
I came up with a likely workable solution, but I still need to think it through some more, by creating a child process. #include // Simulated resources (database and logger) class Logger { std::atomic_bool keepRunning = true; void signalHandler(int signum) { void crowServerFunction(Database& db, Logger& logger) {
} int main() {
} and it stops with SIGINT and SIGHUP showing ./sandbox6 |
Hi @rootrunner, your application architecture is of course your personal business, but I would recommend that you run Crow as the last one in the chain of service launches (databases, cache, etc.), you need to understand that Crow is mainly launched in the main blocking mode flow. I would recommend that you be careful when working in threads and processes, this may lead to undefined behavior of your backend I want to share my example of launching different services, maybe you will find it useful In addition, each of these classes correctly finishes its work after calling the destructor, even if, for example, RabbitMQ was launched in a separate thread to work in non-blocking mode, this can guarantee a complete stop of all your running services int main(int argc, char const *argv[]) {
MongoDB mongo("mongodb://user:pass@localhost:27017");
RabbitMQ rabbitmq;
RabbitMQHandler rabbitmqHandler(rabbitmq);
Crow::App<Authorization> app;
route_auth(app);
route_user(app);
AuthRepository::Start(mongo);
UserRepository::Start(mongo, rabbitmq);
rabbitmq.ConsumeNewThread( // non-blocking run
"amqp://user:pass@localhost",
"exchange", "queue", "route",
RabbitQueueType::Durable,
RabbitExchangeType::Direct
);
app.port(18080).multithreaded().run(); // blocking run
return 0;
} Yes, in fact, I’m making a detached thread for RabbitMQ, but even it can be successfully completed using atomic values or forwarded pointers to the UV driver on which RabbitMQ is running and stop it, the same can be done with any libraries that initially do not allow running asynchronously Well, I hope this is useful for you |
if you want to make a parallel worker or calculation, the best idea would be to make it separately from the HTTP API server, let's say use RabbitMQ or Kafka on a separate host, this is a more local solution, if you need bare sockets for the worker, you can use ZeroMQ to build your network infrastructure from scratch is quite an interesting activity, but it requires a lot of free time, but as always, it’s up to you to decide ✌️ |
@gittiver I see you labeled it as a possible bug. Should you be able to solve it do reply please because I'm running into issues with the child process approach I mentioned last. I'm still trying to solve them though ... |
Apologies for the bad formatting but it just wouldn't accept it as it should.
I have a linux application and the last class I've added uses CrowCpp to serve a website that'll become the gui in the end.
When I interrupt the program by pressing CTRL-C the main program loop just keeps on running. I do not have that issue with instances of other classes.
Everything shuts down cleanly but if I dare run the website it no longer works.
I have eventhandlers in place for amongst others SIGHUP and SIGINT. SIGINT is the equivalent of pressing CTRL-C in a terminal.
Both can be sent as kill -SIGHUP pid and kill -SIGINT pid. The latter is thus the equivalent op pressing CTRL-C.
I made a POC that only installs 2 signal handlers that exhibits the same problem. It could be a bit shorter but I kept the main program loop the same as in the real code.
`#include
#include
#include
#include
#include
#include <crow.h>
class MyCrowApp {
public:
MyCrowApp(unsigned int port) : port(port) {
std::cout << "Constructing MyCrowApp instance." << std::endl;
processingThread = std::thread(&MyCrowApp::runWebserver, this); // Start webserver in a separate thread.
}
~MyCrowApp() {
app.stop();
if (processingThread.joinable()) {
processingThread.join();
}
std::cout << "Destructed MyCrowApp instance." << std::endl;
}
The output when sending SIGINT:
./sandbox4
PID 12069
Constructing MyCrowApp instance.
Webserver starting ...
(2024-06-15 16:59:35) [INFO ] Crow/master server is running at http://0.0.0.0:10088 using 8 threads
(2024-06-15 16:59:35) [INFO ] Call
app.loglevel(crow::LogLevel::Warning)
to hide Info level logs.Sign of life ...
Sign of life ...
-> Command executed -> kill -SIGINT 12069 ( It wouldn't make a difference if I do CTRL-C )
(2024-06-15 16:59:50) [INFO ] Closing IO service 0x73e4f4001fc0
(2024-06-15 16:59:50) [INFO ] Closing IO service 0x73e4f4001fc8
(2024-06-15 16:59:50) [INFO ] Closing IO service 0x73e4f4001fd0
(2024-06-15 16:59:50) [INFO ] Closing IO service 0x73e4f4001fd8
(2024-06-15 16:59:50) [INFO ] Closing IO service 0x73e4f4001fe0
(2024-06-15 16:59:50) [INFO ] Closing IO service 0x73e4f4001fe8
(2024-06-15 16:59:50) [INFO ] Closing IO service 0x73e4f4001ff0
(2024-06-15 16:59:50) [INFO ] Closing main IO service (0x73e4f4001078)
(2024-06-15 16:59:50) [INFO ] Exiting.
Webserver stopped ...
-> The main program loop just continues ...
Sign of life ...
Sign of life ...
-> Command executed -> kill -9 12069
Killed
The ouput when sending SIGHUP:
Notice there is no output from Crow nor log messages from myApp's destructor.
I experimented with Crow's run_async() method and tried several approaches but nothing works.
It is as if Crow does something to the signals that interferes with the other code.
I've got 15 classes in it with x instances and everything destructs neatly but not so the Crow class.
I don't have a clue anymore.
If somebody has an idea do elaborate please.
The text was updated successfully, but these errors were encountered: