fixed: the way how winix is closing

beforehand we made a http connection from the special thread
       now we just send a fastcgi packet to the unix socket

       the old way was broken because it requires the http server to work
       and if the operating system is going to shutdown/reboot then the http server
       can be first closed and consequently the winix cannot wake up from
       the main thread (and will be terminated SIGKILL by the os)
       



git-svn-id: svn://ttmath.org/publicrep/winix/trunk@998 e52654a7-88a9-db11-a3e9-0013d4bc506e
This commit is contained in:
Tomasz Sowa 2015-01-02 07:01:08 +00:00
parent f875bd2944
commit 0a43870e76
2 changed files with 58 additions and 38 deletions

View File

@ -33,6 +33,8 @@
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <pwd.h>
#include <grp.h>
#include <unistd.h>
@ -40,7 +42,7 @@
#include <netinet/in.h>
#include <arpa/inet.h>
#include <utility>
#include <curl/curl.h>
#include <fastcgi.h>
#include "app.h"
#include "plugin.h"
#include "misc.h"
@ -1774,43 +1776,64 @@ void App::WaitForThreads()
size_t App::FetchPageOnExitCurlCallback(char *ptr, size_t size, size_t nmemb, void *userdata)
/*
we send a one FastCGI record at the end when winix closes (to wake up the main thread)
this method is called from the special thread
typedef struct {
unsigned char version;
unsigned char type;
unsigned char requestIdB1;
unsigned char requestIdB0;
unsigned char contentLengthB1;
unsigned char contentLengthB0;
unsigned char paddingLength;
unsigned char reserved;
unsigned char contentData[contentLength];
unsigned char paddingData[paddingLength];
} FCGI_Record;
*/
void App::SendEmptyFastCGIPacket()
{
/*
* without this function the curl library will print the page's content
* to the standart output
*/
return size * nmemb;
}
std::string msg;
sockaddr_un to;
int res;
int s = socket(PF_LOCAL, SOCK_STREAM, 0);
void App::FetchPageOnExit()
{
// stupid trick to break FCGX_Accept_r() function
// even with FCGX_InitRequest(..., ..., FCGI_FAIL_ACCEPT_ON_INTR) the FCGX_Accept_r
// doesn't want to break on a signal
// so we request one page from the server for exiting from FCGX_Accept_r
if( s < 0 )
return;
Lock();
CURL * curl = curl_easy_init();
Unlock();
memset(&to, 0, sizeof(to));
to.sun_len = sizeof(to.sun_len)
+ sizeof(to.sun_family)
+ socket_to_send_on_exit.size()
+ 1; // terminating zero
if( curl )
to.sun_family = AF_UNIX;
snprintf(to.sun_path, sizeof(to.sun_path)/sizeof(char), "%s", socket_to_send_on_exit.c_str());
// actually we can send one byte only
msg += FCGI_VERSION_1;
msg += FCGI_GET_VALUES;
msg += (char)0; // requestid
msg += (char)0;
msg += (char)0; // contentlength
msg += (char)0;
msg += (char)0; // padding length
msg += (char)0;
msg += (char)0; // reserved
res = connect(s, (sockaddr*)&to, sizeof(to));
if( res == 0 )
{
curl_easy_setopt(curl, CURLOPT_URL, url_to_fetch_on_exit.c_str());
curl_easy_setopt(curl, CURLOPT_TCP_NODELAY, 1);
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, FetchPageOnExitCurlCallback);
if( curl_easy_perform(curl) != 0 )
{
Lock();
log << log1 << "App: I cannot correctly fetch a page from the special thread" << logend << logsave;
Unlock();
}
curl_easy_cleanup(curl);
send(s, msg.c_str(), msg.size(), MSG_EOF);
}
close(s);
}
@ -1832,12 +1855,10 @@ int sig;
app->synchro.was_stop_signal = true;
FCGX_ShutdownPending();
// here we don't have to use SSL version so we always use config.url_proto
PT::WideToUTF8(app->config.url_proto, app->url_to_fetch_on_exit);
PT::WideToUTF8(app->config.base_url, app->url_to_fetch_on_exit, false);
PT::WideToUTF8(app->config.fcgi_socket, app->socket_to_send_on_exit);
app->Unlock();
app->FetchPageOnExit();
app->SendEmptyFastCGIPacket();
pthread_exit(0);
return 0;

View File

@ -147,7 +147,7 @@ private:
int fcgi_socket;
Synchro synchro;
pthread_t signal_thread;
std::string url_to_fetch_on_exit;
std::string socket_to_send_on_exit;
std::string send_data_buf;
PT::SpaceToJSON json_generic_serializer;
TextStream<std::wstring> json_out_stream;
@ -225,8 +225,7 @@ private:
void LogGroups();
static void * SpecialThreadForSignals(void*);
static size_t FetchPageOnExitCurlCallback(char *ptr, size_t size, size_t nmemb, void *userdata);
void FetchPageOnExit();
void SendEmptyFastCGIPacket();
void CreateStaticTree();