Patch level : 10.0

Files correlati     : lurch.exe
Ricompilazione Demo : [ ]
Commento            :
Questo maggiordomo non solo e' in grado di ammazzare la servitu' oziosa...
ma anche di risuscitarla quanto questa si suicida!


git-svn-id: svn://10.65.10.50/trunk@19979 c028cbd2-c16b-5b4b-a496-9718f37d4682
This commit is contained in:
guy 2010-01-25 15:36:05 +00:00
parent 28fb3889c5
commit 46d30d0ca2
4 changed files with 253 additions and 197 deletions

View File

@ -15,7 +15,7 @@
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
// headers // headers
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
#include <wx/wxprec.h>
#include "baseserv.h" #include "baseserv.h"
#include <wx/config.h> #include <wx/config.h>
@ -25,12 +25,10 @@
#include <wx/mstream.h> #include <wx/mstream.h>
#include <wx/sckstrm.h> #include <wx/sckstrm.h>
#ifdef WIN32 #ifndef __WXMSW__
#include <wx/fileconf.h> #include <wx/fileconf.h>
#endif #endif
#include <wx/app.h>
/////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////
// Utilities // Utilities
/////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////
@ -589,6 +587,11 @@ const wxString& TBaseServerApp::GetConfigName() const
void TBaseServerApp::SetConfigString(const wxChar* key, const wxChar* val, const wxChar* app) const void TBaseServerApp::SetConfigString(const wxChar* key, const wxChar* val, const wxChar* app) const
{ {
#ifdef __WXMSW__
if (app == NULL || *app == '\0')
app = GetAppName();
::WritePrivateProfileString(app, key, val, GetConfigName());
#else
wxFileConfig ini("", "", GetConfigName(), "", wxCONFIG_USE_LOCAL_FILE | wxCONFIG_USE_RELATIVE_PATH); wxFileConfig ini("", "", GetConfigName(), "", wxCONFIG_USE_LOCAL_FILE | wxCONFIG_USE_RELATIVE_PATH);
wxString str; wxString str;
if (app == NULL || *app == '\0') if (app == NULL || *app == '\0')
@ -596,6 +599,7 @@ void TBaseServerApp::SetConfigString(const wxChar* key, const wxChar* val, const
str << '/' << app; str << '/' << app;
ini.SetPath(str); ini.SetPath(str);
ini.Write(key, val); ini.Write(key, val);
#endif
} }
void TBaseServerApp::SetConfigInt(const wxChar* key, int val, const wxChar* app) const void TBaseServerApp::SetConfigInt(const wxChar* key, int val, const wxChar* app) const
@ -606,13 +610,19 @@ void TBaseServerApp::SetConfigInt(const wxChar* key, int val, const wxChar* app)
wxString TBaseServerApp::GetConfigString(const wxChar* key, const wxChar* def, const wxChar* app) const wxString TBaseServerApp::GetConfigString(const wxChar* key, const wxChar* def, const wxChar* app) const
{ {
wxFileConfig ini("", "", GetConfigName(), "", wxCONFIG_USE_LOCAL_FILE | wxCONFIG_USE_RELATIVE_PATH);
wxString str; wxString str;
if (app == NULL || *app == '\0') if (app == NULL || *app == '\0')
app = GetAppName(); app = GetAppName();
#ifdef __WXMSW__
wxChar value[512]; memset(value, 0, sizeof(value));
const int len = ::GetPrivateProfileString(app, key, def, value, sizeof(value)-1, GetConfigName());
str = len <= 0 ? def : value;
#else
wxFileConfig ini("", "", GetConfigName(), "", wxCONFIG_USE_LOCAL_FILE | wxCONFIG_USE_RELATIVE_PATH);
str << '/' << app; str << '/' << app;
ini.SetPath(str); ini.SetPath(str);
ini.Read(key, &str, def); ini.Read(key, &str, def);
#endif
return str; return str;
} }

View File

@ -1,11 +1,12 @@
#include <wx/wxprec.h> #ifndef __BASESERV_H__
#define __BASESERV_H__
#include <wx/app.h>
#include <wx/datetime.h> #include <wx/datetime.h>
#include <wx/hash.h>
#include <wx/snglinst.h> #include <wx/snglinst.h>
#include <wx/socket.h> #include <wx/socket.h>
#include <wx/wfstream.h> #include <wx/wfstream.h>
#ifdef LINUX
#include <wx/app.h>
#endif
#include "xml.h" #include "xml.h"
@ -150,3 +151,5 @@ public:
}; };
TBaseServerApp& GetServerApp(); TBaseServerApp& GetServerApp();
#endif

View File

@ -3,56 +3,36 @@
#include <wx/config.h> #include <wx/config.h>
#include <wx/filename.h> #include <wx/filename.h>
#include <wx/process.h> #include <wx/process.h>
#ifdef WIN32 #include <wx/timer.h>
#include <wx/fileconf.h>
#endif
#include <ctype.h>
///////////////////////////////////////////////////////////
// TProcess declaration
///////////////////////////////////////////////////////////
class TLurchServer; //segnaposto della TLurchServer che serve alla TProcess
class TProcess : public wxProcess
{
TLurchServer* m_pLurch;
wxString m_strApp;
protected:
virtual void OnTerminate(int pid, int status);
public:
void ForcePid(int pid) { SetPid(pid); }
TProcess(TLurchServer* pLurch, const wxString& strApp) : m_pLurch(pLurch), m_strApp(strApp) {}
};
/////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////
// TLurchServer declaration // TLurchServer declaration
/////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////
//classe TProcessHashMap derivata da wxHashMap (è una specie di assocarray!) //classe TProcessHashMap derivata da wxHashMap (è l'equivalente di TAssoc_array)
WX_DECLARE_HASH_MAP( wxString, wxProcess*, wxStringHash, wxStringEqual, TProcessHashMap ); WX_DECLARE_HASH_MAP( wxString, wxProcess*, wxStringHash, wxStringEqual, TProcessHashMap );
class TLurchServer : public TBaseServerApp class TLurchServer : public TBaseServerApp
{ {
TProcessHashMap m_ProcMap; TProcessHashMap m_hmProcMap;
wxTimer m_Timer; wxSemaphore m_Semaphore;
int m_nFreq; wxTimer m_PingTimer;
wxArrayString m_aServers;
DECLARE_EVENT_TABLE(); DECLARE_EVENT_TABLE();
protected: protected:
virtual const wxChar* GetAppName() const; virtual const wxChar* GetAppName() const;
virtual bool Initialization(); virtual bool Initialization();
void OnTimer(wxTimerEvent& evt); void OnTimer(wxTimerEvent& evt);
bool RestartTimer(); void OnEndProcess(wxProcessEvent& evt);
void AddMiniForm(TXmlItem& tr, const wxChar* action, const wxChar* app, const wxChar* prompt) const; TXmlItem& AddMiniForm(TXmlItem& tr, const wxChar* action, const wxChar* app, const wxChar* prompt) const;
void EnumerateVariables(const wxString& strApp, wxArrayString& arr) const; void EnumerateVariables(const wxString& strApp, wxArrayString& arr) const;
void CreateServersList(wxArrayString& arr) const; const wxArrayString& GetServersList();
const TProcessHashMap& GetRunningServers() { return m_hmProcMap; }
bool PingProcess(const wxString& strApp); bool PingProcess(const wxString& strApp);
void StopProcess(const wxString& strApp); void StopProcess(const wxString& strApp);
wxString StartProcess(const wxString& strApp); wxString StartProcess(const wxString& strApp);
@ -70,116 +50,150 @@ public:
//metodi riguardanti l'interfaccia html //metodi riguardanti l'interfaccia html
void ProcessFormStart(const THashTable& args, wxSocketBase& sock); void ProcessFormStart(const THashTable& args, wxSocketBase& sock);
void ProcessFormStop(const THashTable& args, wxSocketBase& sock); void ProcessFormStop(const THashTable& args, wxSocketBase& sock);
void ProcessFormRestart(const THashTable& args, wxSocketBase& sock);
void ProcessFormConfig(const THashTable& args, wxSocketBase& sock); void ProcessFormConfig(const THashTable& args, wxSocketBase& sock);
void ProcessFormUpdate(THashTable& args, wxSocketBase& sock); void ProcessFormUpdate(THashTable& args, wxSocketBase& sock);
void CallCgi(wxString& strFileName, wxSocketBase& sock); void CallCgi(wxString& strFileName, wxSocketBase& sock);
TLurchServer();
}; };
/////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////
// TProcess implementation
///////////////////////////////////////////////////////////
void TProcess::OnTerminate(int pid, int WXUNUSED(status))
{
SetPid(pid);
m_pLurch->ForgetProcess(m_strApp);
}
///////////////////////////////////////////////////////////
// TLurchServer implementation // TLurchServer implementation
/////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////
BEGIN_EVENT_TABLE(TLurchServer, TBaseServerApp) BEGIN_EVENT_TABLE(TLurchServer, TBaseServerApp)
EVT_TIMER(wxID_ANY, TLurchServer::OnTimer) EVT_TIMER(wxID_ANY, TLurchServer::OnTimer)
EVT_END_PROCESS(wxID_ANY, TLurchServer::OnEndProcess)
END_EVENT_TABLE() END_EVENT_TABLE()
#ifndef max
#define max(a,b) ((a)>(b) ? (a) : (b))
#endif
bool TLurchServer::PingProcess(const wxString& strApp) bool TLurchServer::PingProcess(const wxString& strApp)
{ {
bool bPinged = false; bool bPinged = false;
TProcess* pProcess = (TProcess*)m_ProcMap[strApp];
if (pProcess != NULL) const wxString strPort = GetConfigString("Port", "", strApp);
if (!strPort.IsEmpty())
{ {
const wxString strPort = GetConfigString("Port", "", strApp); const int nInterval = m_PingTimer.GetInterval(); // msec
if (!strPort.IsEmpty()) const int nTimeOut = max(nInterval/4, 250); // msec
wxIPV4address ipAddress;
ipAddress.LocalHost();
ipAddress.Service(strPort);
wxSocketClient sSock(wxSOCKET_NOWAIT);
sSock.Connect(ipAddress, false);
if (sSock.WaitOnConnect(0, nTimeOut))
{ {
const int nTimeOut = m_nFreq > 3000 ? m_nFreq / 3000 : 1; sSock.Discard(); // Tralascia eventuali dati in arrivo non richiesti
wxIPV4address ipAddress; const wxString strPing = wxT("PING\n");
ipAddress.LocalHost(); sSock.Write(strPing, strPing.Len());
ipAddress.Service(strPort); if (sSock.WaitForWrite(0, nTimeOut))
wxSocketClient sSock(wxSOCKET_NOWAIT);
sSock.Connect(ipAddress, false);
if (sSock.WaitOnConnect(nTimeOut))
{ {
sSock.Write("PING\n", 5); ::wxMilliSleep(nTimeOut); // Triste necessita' :-( Aspetto qui ...
if (sSock.WaitForWrite(nTimeOut)) char buffer[8]; memset(buffer, 0, sizeof(buffer));
{ sSock.Read(buffer, 4);
char buffer[8]; memset(buffer, 0, sizeof(buffer)); if (sSock.WaitForRead(0, 1)) // ... ma poi non aspetto qua :-)
sSock.Read(buffer, 4); bPinged = wxStrncmp(buffer, "PONG", 4) == 0;
if (sSock.WaitForRead(nTimeOut)) sSock.Discard(); // Tralascia ulteriori dati in arrivo
bPinged = wxStrcmp(buffer, "PONG") == 0;
}
} }
} }
} }
return bPinged; return bPinged;
} }
void TLurchServer::OnTimer(wxTimerEvent& WXUNUSED(evt)) void TLurchServer::OnTimer(wxTimerEvent& evt)
{ {
m_Timer.Stop(); if (m_Semaphore.TryWait() != wxSEMA_NO_ERROR)
const wxString strApp = "Authorization";
if (!PingProcess(strApp))
{ {
TProcess* pProcess = (TProcess*)m_ProcMap[strApp]; evt.Skip();
wxKillError ke = pProcess->Kill(pProcess->GetPid()); return;
if (ke == wxKILL_OK) }
WriteLog(strApp + " killed!");
else const TProcessHashMap& hmServers = GetRunningServers();
{ const int nServers = hmServers.size();
wxString strMsg; if (nServers > 0) // Is anybody out there?
strMsg << "Error " << ke << " killing " << strApp; {
WriteLog(strMsg); const int nRandomIndex = rand() % nServers;
} wxString strApp; // Usually "Authorization"
wxSleep(2); TProcessHashMap::const_iterator it;
StartProcess(strApp); for (it = hmServers.begin(); it != hmServers.end(); ++it)
strApp = it->first;
if (!PingProcess(strApp))
{
wxProcess* pProcess = m_hmProcMap[strApp];
wxKillError ke = pProcess->Kill(pProcess->GetPid());
if (ke == wxKILL_OK)
WriteLog(strApp + _(" killed!"));
else
{
wxString strMsg;
strMsg << _("Error ") << ke << _(" killing ") << strApp;
WriteLog(strMsg);
}
wxSleep(2);
StartProcess(strApp);
}
}
m_Semaphore.Post();
}
void TLurchServer::OnEndProcess(wxProcessEvent& evt)
{
TProcessHashMap::const_iterator it;
for (it = m_hmProcMap.begin(); it != m_hmProcMap.end(); ++it)
{
const wxProcess* p = it->second;
if (p->GetPid() == evt.GetPid())
{
ForgetProcess(it->first);
break;
}
} }
RestartTimer();
} }
const wxChar* TLurchServer::GetAppName() const const wxChar* TLurchServer::GetAppName() const
{ return wxT("Lurch"); }
const wxArrayString& TLurchServer::GetServersList()
{ {
return "Lurch"; if (m_aServers.IsEmpty())
{
wxFileInputStream ini(GetConfigName());
const size_t size = ini.GetSize();
wxChar* buff = new wxChar[size];
ini.Read(buff, size);
const char* aperta = strchr(buff, '[');
while (aperta != NULL)
{
char* chiusa = (char*)strchr(aperta+1, ']');
if (chiusa != NULL)
{
*chiusa = '\0';
wxString str = aperta+1;
m_aServers.Add(str);
aperta = strchr(chiusa+1, '[');
}
else
break;
}
}
return m_aServers;
} }
void TLurchServer::CreateServersList(wxArrayString& arr) const TXmlItem& TLurchServer::AddMiniForm(TXmlItem& tr, const wxChar* action, const wxChar* app, const wxChar* prompt) const
{ {
wxFileInputStream ini(GetConfigName()); TXmlItem& td = tr.AddChild("td").SetAttr("width", "10%");
const size_t size = ini.GetSize(); td.SetAttr("align", "center");
wxChar* buff = new wxChar[size]; td.SetAttr("valign", "center"); // Lo ignora ma insisto
ini.Read(buff, size);
TXmlItem& form = td.AddChild("form");
const char* aperta = strchr(buff, '[');
while (aperta != NULL)
{
char* chiusa = (char*)strchr(aperta+1, ']');
if (chiusa != NULL)
{
*chiusa = '\0';
wxString str = aperta+1;
arr.Add(str);
aperta = strchr(chiusa+1, '[');
}
else
break;
}
delete buff;
}
void TLurchServer::AddMiniForm(TXmlItem& tr, const wxChar* action, const wxChar* app, const wxChar* prompt) const
{
TXmlItem& td = tr.AddChild("td").SetAttr("width", "15%");
TXmlItem& form = td.AddChild("center").AddChild("form");
form.SetAttr("action", action); form.SetAttr("action", action);
TXmlItem& name = form.AddChild("input"); TXmlItem& name = form.AddChild("input");
@ -189,6 +203,7 @@ void TLurchServer::AddMiniForm(TXmlItem& tr, const wxChar* action, const wxChar*
TXmlItem& submit = form.AddChild("input"); TXmlItem& submit = form.AddChild("input");
submit.SetAttr("type", "submit"); submit.SetAttr("type", "submit");
submit.SetAttr("value", prompt); submit.SetAttr("value", prompt);
return submit;
} }
void TLurchServer::GenerateFile(wxString& strFilename) void TLurchServer::GenerateFile(wxString& strFilename)
@ -203,30 +218,21 @@ void TLurchServer::GenerateFile(wxString& strFilename)
strFilename = GetTempFilename(); strFilename = GetTempFilename();
const wxString strLurchName = GetAppName(); const wxString strLurchName = GetAppName();
wxArrayString arr; CreateServersList(arr); const wxArrayString& arr = GetServersList();
for (size_t i = 0; i < arr.GetCount(); i++) for (size_t i = 0; i < arr.GetCount(); i++)
{ {
const bool bLurch = arr[i] == strLurchName; const wxString& strApp = arr[i];
wxFileConfig ini("", "", GetConfigName(), "", wxCONFIG_USE_LOCAL_FILE | wxCONFIG_USE_RELATIVE_PATH); const bool bLurch = strApp == strLurchName;
wxString str; const wxString strHost = GetConfigString("Host", "127.0.0.1", strApp);
str << '/' << arr[i]; const int nPort = GetConfigInt("Port", 3883, strApp);
ini.SetPath(str); const wxString strIcon = GetConfigString("Icon", "euro.gif", strApp);
wxString strHost; const wxSingleInstanceChecker sic(strApp);
ini.Read("Host", &strHost, "127.0.0.1");
int nPort;
ini.Read("Port", &nPort, 3883);
wxString strIcon;
ini.Read("Icon", &strIcon, "euro.gif");
const wxSingleInstanceChecker sic(arr[i]);
const bool bRunning = sic.IsAnotherRunning(); const bool bRunning = sic.IsAnotherRunning();
TXmlItem& tr = table.AddChild("tr"); TXmlItem& tr = table.AddChild("tr");
TXmlItem& td0 = tr.AddChild("td"); TXmlItem& td0 = tr.AddChild("td");
td0.SetAttr("width", "15%"); td0.SetAttr("align", "center"); td0.SetAttr("width", "10%"); td0.SetAttr("align", "center");
TXmlItem& a = td0.AddChild("a"); TXmlItem& a = td0.AddChild("a");
if (!bLurch && bRunning) if (!bLurch && bRunning)
{ {
@ -236,8 +242,17 @@ void TLurchServer::GenerateFile(wxString& strFilename)
TXmlItem& img = a.AddChild("img"); TXmlItem& img = a.AddChild("img");
img.SetAttr("src", strIcon); img.SetAttr("border", 0L); img.SetAttr("alt", arr[i]); img.SetAttr("src", strIcon); img.SetAttr("border", 0L); img.SetAttr("alt", arr[i]);
AddMiniForm(tr, (bRunning || bLurch) ? "kill.cgi" : "start.cgi", arr[i], (bRunning || bLurch) ? "Stop" : "Start"); TXmlItem& buttStart = AddMiniForm(tr, "start.cgi", arr[i], _("Start"));
AddMiniForm(tr, "config.cgi", arr[i], "Configure"); if (bRunning || bLurch)
buttStart.SetAttr(wxT("type"), wxT("hidden"));
TXmlItem& buttStop = AddMiniForm(tr, "kill.cgi", arr[i], _("Stop"));
if (!(bRunning || bLurch))
buttStop.SetAttr(wxT("type"), wxT("hidden"));
TXmlItem& buttRestart = AddMiniForm(tr, "restart.cgi", arr[i], _("Restart"));
if (!(bRunning && !bLurch))
buttRestart.SetAttr(wxT("type"), wxT("hidden"));
TXmlItem& a3 = tr.AddChild("td").AddChild("a"); TXmlItem& a3 = tr.AddChild("td").AddChild("a");
if (!bLurch && bRunning) if (!bLurch && bRunning)
@ -264,7 +279,7 @@ void TLurchServer::GenerateFile(wxString& strFilename)
TXmlItem& tr2 = panel.AddChild("tr"); TXmlItem& tr2 = panel.AddChild("tr");
tr2.AddChild("td").AddEnclosedText("Ping Frequency"); tr2.AddChild("td").AddEnclosedText("Ping Frequency");
wxString strFreq; strFreq << m_nFreq/1000; wxString strFreq; strFreq << m_PingTimer.GetInterval()/1000;
tr2.AddChild("td").AddEnclosedText(strFreq); tr2.AddChild("td").AddEnclosedText(strFreq);
html.Save(strFilename); html.Save(strFilename);
@ -301,22 +316,6 @@ bool TLurchServer::IsCgiName(wxString strFilename) const
return strExt == "cgi" || strExt == "exe"; return strExt == "cgi" || strExt == "exe";
} }
bool TLurchServer::RestartTimer()
{
bool ok = true;
if (m_nFreq > 0)
{
ok = m_Timer.Start(m_nFreq) && m_Timer.IsRunning();
if (!ok)
{
wxString strMsg;
strMsg << "Error starting timer with " << m_nFreq << " ms frequency";
WriteLog(strMsg);
}
}
return ok;
}
wxString TLurchServer::StartProcess(const wxString& strApp) wxString TLurchServer::StartProcess(const wxString& strApp)
{ {
bool ok = false; bool ok = false;
@ -337,28 +336,26 @@ wxString TLurchServer::StartProcess(const wxString& strApp)
fnPath.SetPath(GetServerPath()); fnPath.SetPath(GetServerPath());
fnPath.SetFullName(strRun); fnPath.SetFullName(strRun);
TProcess* pProcess = new TProcess(this, strApp); wxProcess* pProcess = wxProcess::Open(fnPath.GetFullPath());
const long nProc = wxExecute(fnPath.GetFullPath(), wxEXEC_ASYNC, pProcess); if (pProcess == NULL)
if (nProc == 0 || nProc == -1)
{ {
strMessage.Printf("Can't run %s executable (%s)", strApp.c_str(), strRun.c_str()); strMessage.Printf(_("Can't run %s executable (%s)"), strApp.c_str(), strRun.c_str());
delete pProcess;
} }
else else
{ {
pProcess->ForcePid(nProc); m_hmProcMap[strApp] = pProcess; // memorizza il numero del processo che ha lanciato per poterlo usare in fase di controllo
m_ProcMap[strApp] = pProcess; //memorizza il numero del processo che ha lanciato per poterlo usare in fase di controllo
strMessage = wxEmptyString; strMessage = wxEmptyString;
::wxSleep(1); // Lascia il tempo di inizializzarsi prima di compinciare a pingarlo!
} }
} }
else else
strMessage.Printf("Can't find %s executable (%s)", strApp.c_str(), strRun.c_str()); strMessage.Printf(_("Can't find %s executable (%s)"), strApp.c_str(), strRun.c_str());
} }
else else
strMessage.Printf("%s il already running", strApp.c_str()); strMessage.Printf(_("%s il already running"), strApp.c_str());
if (strMessage.IsEmpty()) if (strMessage.IsEmpty())
WriteLog(strApp + " started."); WriteLog(strApp + _(" started."));
else else
WriteLog(strMessage); WriteLog(strMessage);
@ -372,16 +369,16 @@ void TLurchServer::ProcessFormStart(const THashTable& args, wxSocketBase& sock)
{ {
const wxString strMessage = StartProcess(strApp); const wxString strMessage = StartProcess(strApp);
if (strMessage.IsEmpty()) if (strMessage.IsEmpty())
MessageBox("Server Started", strApp, sock); MessageBox(_("Server Started"), strApp, sock);
else else
MessageBox("ERROR", strMessage, sock); MessageBox(_("ERROR"), strMessage, sock);
} }
} }
bool TLurchServer::ForgetProcess(const wxString& strApp) bool TLurchServer::ForgetProcess(const wxString& strApp)
{ {
WriteLog(strApp + " terminated."); WriteLog(strApp + _(" terminated."));
return m_ProcMap.erase(strApp) != 0; return m_hmProcMap.erase(strApp) != 0;
} }
void TLurchServer::StopProcess(const wxString& strApp) void TLurchServer::StopProcess(const wxString& strApp)
@ -397,14 +394,25 @@ void TLurchServer::StopProcess(const wxString& strApp)
wxSocketClient sock; wxSocketClient sock;
if (sock.Connect(addr)) if (sock.Connect(addr))
{ {
// Prima provo con le buone inviando una richiesta di stop
const wxString str = "GET /stop.cgi HTTP/1.1\r\n\r\n"; const wxString str = "GET /stop.cgi HTTP/1.1\r\n\r\n";
sock.Write(str, str.Length()); sock.Write(str, str.Length());
if (strHost == "localhost") if (addr.IsLocalHost())
{ {
const wxSingleInstanceChecker sic(strApp); const wxSingleInstanceChecker sic(strApp);
for (int i = 0; i < 5 && sic.IsAnotherRunning(); i++) int i;
for (i = 5; i >= 0 && sic.IsAnotherRunning(); i--)
wxSleep(1); wxSleep(1);
ForgetProcess(strApp); // Se le buone non hanno funzionato ... passo alle cattive
if (i < 0)
{
wxProcess* p = m_hmProcMap[strApp];
if (p != NULL)
{
p->Kill(p->GetPid());
ForgetProcess(strApp);
}
}
} }
} }
} }
@ -412,24 +420,46 @@ void TLurchServer::StopProcess(const wxString& strApp)
void TLurchServer::ProcessFormStop(const THashTable& args, wxSocketBase& sock) void TLurchServer::ProcessFormStop(const THashTable& args, wxSocketBase& sock)
{ {
const wxString strApp = args.Get("App"); if (m_Semaphore.Wait() == wxSEMA_NO_ERROR)
if (strApp == GetAppName()) // Stop myself! {
{ const wxString strApp = args.Get("App");
wxArrayString app; CreateServersList(app); if (strApp == GetAppName() || strApp.IsEmpty()) // Stop myself!
for (size_t i = 0; i < app.GetCount(); i++) {
{ m_PingTimer.Stop(); // Stop ping process!
if (app[i] != GetAppName()) // Stop Children only! // Fill a safe array of names before killing the processes stored in the hash map
{ const TProcessHashMap& hmServers = GetRunningServers(); // Hash map of the running processes
const wxSingleInstanceChecker sic(app[i]); wxArrayString aRunner; // Array of the names of the runners
if (sic.IsAnotherRunning()) TProcessHashMap::const_iterator it;
StopProcess(app[i]); for (it = hmServers.begin(); it != hmServers.end(); ++it)
} aRunner.Add(it->first);
} for (size_t i = 0; i < aRunner.GetCount(); i++)
} StopProcess(aRunner[i]);
StopProcess(strApp); ExitMainLoop();
MessageBox("Server stopped", strApp, sock); }
else
StopProcess(strApp);
MessageBox("Server stopped", strApp, sock);
m_Semaphore.Post();
}
} }
void TLurchServer::ProcessFormRestart(const THashTable& args, wxSocketBase& sock)
{
const wxString strApp = args.Get("App");
if (!strApp.IsEmpty() && strApp != GetAppName())
{
if (m_Semaphore.Wait() == wxSEMA_NO_ERROR)
{
StopProcess(strApp);
::wxSleep(2);
ProcessFormStart(args, sock);
m_Semaphore.Post();
}
}
}
void TLurchServer::EnumerateVariables(const wxString& strApp, wxArrayString& arr) const void TLurchServer::EnumerateVariables(const wxString& strApp, wxArrayString& arr) const
{ {
wxFileInputStream inf(GetConfigName()); wxFileInputStream inf(GetConfigName());
@ -542,10 +572,13 @@ void TLurchServer::CallCgi(wxString& strFileName, wxSocketBase& sock)
if (strExt == "cgi") if (strExt == "cgi")
{ {
strName.MakeLower();
if (strName == "start") if (strName == "start")
ProcessFormStart(hashArgs, sock); else ProcessFormStart(hashArgs, sock); else
if (strName == "kill") if (strName == "kill")
ProcessFormStop(hashArgs, sock); else ProcessFormStop(hashArgs, sock); else
if (strName == "restart")
ProcessFormRestart(hashArgs, sock); else
if (strName == "config") if (strName == "config")
ProcessFormConfig(hashArgs, sock); else ProcessFormConfig(hashArgs, sock); else
if (strName == "update") if (strName == "update")
@ -593,23 +626,32 @@ void TLurchServer::ProcessHttpPost(wxString cmd, wxSocketBase& outs)
bool TLurchServer::Initialization() bool TLurchServer::Initialization()
{ {
m_nFreq = GetConfigInt("PingFreq") * 1000; // sec to msec const wxArrayString& arr = GetServersList();
wxArrayString arr; CreateServersList(arr);
for (size_t i = 0; i < arr.GetCount(); i++) for (size_t i = 0; i < arr.GetCount(); i++)
{ {
const wxString& strApp = arr[i]; const wxString& strApp = arr[i];
const bool bAutorun = GetConfigBool("Autorun", false, strApp); if (strApp != GetAppName())
if (bAutorun) {
StartProcess(strApp); const bool bAutorun = GetConfigBool("Autorun", false, strApp);
if (bAutorun)
StartProcess(strApp);
}
} }
RestartTimer(); const int nFreq = GetConfigInt("PingFreq");
if (nFreq > 0)
{
m_PingTimer.Start(nFreq * 1000); // sec to msec
m_Semaphore.Post(); // GREEN!
}
return true; return true;
} }
// Istanziare l'applicazione principale // Istanziare l'applicazione principale
IMPLEMENT_APP(TLurchServer) IMPLEMENT_APP(TLurchServer)
TLurchServer::TLurchServer()
: m_Semaphore(0 /* RED! */, 1 /* mutex like behaviour */)
{ }

View File

@ -1,4 +1,5 @@
#include <wx/wx.h> #include <wx/wx.h>
#include "wx/mstream.h" #include "wx/mstream.h"
#include <wx/wfstream.h> #include <wx/wfstream.h>