Skip to content
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

Signal Handling with gracious service stop #223

Closed
gDev95 opened this issue Jun 12, 2017 · 13 comments
Closed

Signal Handling with gracious service stop #223

gDev95 opened this issue Jun 12, 2017 · 13 comments
Assignees
Milestone

Comments

@gDev95
Copy link

gDev95 commented Jun 12, 2017

Hi,

I am trying to find a good way to stop the server based on Signals sent.

I tried to write a handler method where I pass A) a const int sig_number and B) a service object to be able to stop the server for example if the Signal is SIGINT or SIGTERM. However, as the standard function signal() as well am I not allowed to pass any other parameters to the function set_method_handler().

How could I stop the server graciously with the stop() method after a Signal was caught?

If you could give me opinions and ideas how a way to accomplish this I would be forever grateful!

EDIT
I declare now the Service Object as static outside of main() making it shared. Yes it kinda work but
server->stop(); inside my signal_handler() terminates the program but throws an exception

std::exception
libc++abi.dylib: terminating
Abort trap: 6

Not sure why and how to handle this.

main() looks as follows:

int main(const int, const char**) {
   try {
	   // multipath resource

	   auto resource = make_shared<Resource>();
	   resource->set_paths( { "/app/{id: [0-9]*}", "/app/{id: [0-9]*}/cohorts" } );


	   // set GET handler for endpoints
	   resource->set_method_handler("GET", get_method_handler_end);



		// Used Port: 8080
	   auto settings = make_shared<Settings>();
	   settings-> set_port( 8080 );
	   // 10 threads possible
	   settings->set_worker_limit( 10 );
	   settings->set_default_header( "Connection", "close" );

	   // setup Server

	   server->publish( resource );



	   server->set_ready_handler( ready_handler );
	   server->set_signal_handler(SIGINT, sigint_handler);

	   //server.set_signal_handler(SIGHUP,sighup_handler);
	   //server.set_signal_handler(SIGTSTP, sigsuspend_handler);
	   server->start( settings );


	   return EXIT_SUCCESS;
   }
	catch(exception &e)
	{
		cout << e.what();
	}
}
@ben-crowhurst
Copy link
Member

Have you taken a look at the signalling example?

@gDev95
Copy link
Author

gDev95 commented Jun 12, 2017

My handler:

void sigint_handler(int  sig_number)
{


	fprintf( stderr, "\nReceived SIGINT signal number '%i'.\n", sig_number );
	ctrl_c_count++;
	if(ctrl_c_count >= 2)
	{
		char answer[10];
		printf("\nReally Exit? [y/n]");
		flush(cout);
		cin >> answer;
		if (answer[0] == 'y' || answer[0] == 'Y') {

			try
			{
				printf("Exiting, Server will stop running...\n");
				server->stop();
				return;
			}
			catch(exception e)
			{
				cout << e.what() << endl;
			}

			//exit(0);
		} else {
			printf("\n Continuing...\n");
			flush(cout);
			// reset counter
			ctrl_c_count = 0;
		}
	}
}

I have. But you are just printing out the signal that was given, you do not stop the service...

@ben-crowhurst
Copy link
Member

ben-crowhurst commented Jun 13, 2017

Looks like you have a reasonable implementation in play. 👍

@ben-crowhurst
Copy link
Member

ben-crowhurst commented Jun 22, 2017

Capture the service during lambda definition, alternatively call bind on get_method_handler_end.

resource->set_method_handler("GET",  [service]( ... )
{
    service->stop( );
} );

Further Reading
Lambda Expressions
std::function
std::bind

See project examples for further details.

@gDev95
Copy link
Author

gDev95 commented Jun 22, 2017

Why would I want to call bind on the get_method_handler and not the signal_handler?

@ben-crowhurst
Copy link
Member

Apologies I mean sigint_handler.

@gDev95
Copy link
Author

gDev95 commented Jun 22, 2017

The problem I mentioned again in the second reopening issue was that set_signal_handler takes two parameters, const int signal and std::function <void <const int>>. Capturing service during lambda definition throws an error because server is of <void (*)>, or NOT void <const int>.

@ben-crowhurst
Copy link
Member

Please provide a complete example with build commands.

@gDev95
Copy link
Author

gDev95 commented Jun 22, 2017

auto server = make_shared<Service>( );
int main() {
try {


	auto endpoint_A = make_shared<Resource>();
	auto endpoint_B = make_shared<Resource>();

	endpoint_A->set_path("/apps/{id: [0-9]*}/cohorts");
	endpoint_B->set_path("/apps/{id: [0-9]*}");

	endpoint_A->set_method_handler("GET", get_handler_A);
	endpoint_B->set_method_handler("GET", get_handler_B);


	auto settings = make_shared<Settings> ();
	settings-> set_port( 3030 );
	// 10 threads limit
	settings->set_worker_limit( 10 );

	server->publish( endpoint_A );
	server->publish( endpoint_B);

	server->set_ready_handler( ready_handler );
	
	server->set_signal_handler(SIGINT, [](){

		server->stop();
	} )

	server->start( settings );

	return EXIT_SUCCESS;
}
catch(exception &e)
{
	cout << e.what();
}
}

Following Error occurs:

error: no viable conversion from '(lambda at /Users/adjust/Documents/C++/cpp-service/webservice.cpp:132:37)' to 'const std::function<void (const int)>'
        server->set_signal_handler(SIGINT, [](){ 

The error points to the empty capture list, however server is global.

@ben-crowhurst
Copy link
Member

ben-crowhurst commented Jun 22, 2017

server->set_signal_handler(SIGINT, [server](const int signum){
		server->stop();
} );

See C++11 standard specification for details.

@ben-crowhurst
Copy link
Member

ben-crowhurst commented Jun 22, 2017

The error points to an invalid function signature.

@gDev95
Copy link
Author

gDev95 commented Jun 22, 2017

Thank you very much, I am sorry I did not figure that out myself.

@ben-crowhurst
Copy link
Member

Not at all. Enjoy using Restbed.

ben-crowhurst added a commit that referenced this issue Jul 29, 2017
fadedreamz pushed a commit to fadedreamz/restbed that referenced this issue Nov 3, 2017
clrusby pushed a commit to clrusby/restbed that referenced this issue Jul 27, 2018
maggu2810 pushed a commit to maggu2810/restbed that referenced this issue Mar 14, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants