Here is the patch.
JDR
--
=============================================================
John D. Robertson, Computer / Engineering Consultant
Robertson & Robertson Consultants, Inc.
3637 West Georgia Rd.
Pelzer, SC 29669
Phone: (864) 243-2436
Email: j...@rrci.com
WWW: http://www.rrci.com
Blog: http://oopinc.blogspot.com
/*
* Copyright (C) 2011 Emweb bvba, Kessel-Lo, Belgium.
*
* See the LICENSE file for terms of use.
*/
#if !defined(_WIN32)
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <pthread.h>
#else
#include <process.h>
#endif // !_WIN32
#include <boost/algorithm/string.hpp>
#include "Wt/WIOService"
#include "Wt/WResource"
#include "Wt/WServer"
#include "Configuration.h"
#include "WebController.h"
namespace Wt {
LOGGER("WServer");
namespace {
bool CatchSignals = true;
}
WServer *WServer::instance_ = 0;
WServer::Exception::Exception(const std::string& what)
: WException(what)
{ }
void WServer::init(const std::string& wtApplicationPath,
const std::string& configurationFile)
{
application_ = wtApplicationPath;
configurationFile_ = configurationFile;
ownsIOService_ = true;
ioService_ = 0;
webController_ = 0;
configuration_ = 0;
logger_.addField("datetime", false);
logger_.addField("app", false);
logger_.addField("session", false);
logger_.addField("type", false);
logger_.addField("message", true);
instance_ = this;
}
void WServer::destroy()
{
if (ownsIOService_) {
delete ioService_;
ioService_ = 0;
}
delete webController_;
delete configuration_;
instance_ = 0;
}
void WServer::setIOService(WIOService& ioService)
{
if (ioService_) {
LOG_ERROR("setIOService(): already have an IO service");
return;
}
ioService_ = &ioService;
ownsIOService_ = false;
}
WIOService& WServer::ioService()
{
if (!ioService_) {
ioService_ = new WIOService();
ioService_->setThreadCount(configuration().numThreads());
}
return *ioService_;
}
void WServer::setAppRoot(const std::string& path)
{
if (configuration_)
LOG_ERROR("setAppRoot(): too late, already configured");
appRoot_ = path;
}
std::string WServer::appRoot() const
{
// FIXME we should const-correct Configuration too
return const_cast<WServer *>(this)->configuration().appRoot();
}
void WServer::setConfiguration(const std::string& file)
{
setConfiguration(file, application_);
}
void WServer::setConfiguration(const std::string& file,
const std::string& application)
{
if (configuration_)
LOG_ERROR("setConfigurationFile(): too late, already configured");
configurationFile_ = file;
application_ = application;
}
WLogEntry WServer::log(const std::string& type) const
{
WLogEntry e = logger_.entry(type);
e << WLogger::timestamp << WLogger::sep
<< getpid() << WLogger::sep
<< /* sessionId << */ WLogger::sep
<< '[' << type << ']' << WLogger::sep;
return e;
}
void WServer::initLogger(const std::string& logFile,
const std::string& logConfig)
{
if (!logFile.empty())
logger_.setFile(logFile);
if (!logConfig.empty())
logger_.configure(logConfig);
if (!description_.empty())
LOG_INFO("initializing " << description_);
}
Configuration& WServer::configuration()
{
if (!configuration_) {
if (appRoot_.empty())
appRoot_ = Configuration::locateAppRoot();
if (configurationFile_.empty())
configurationFile_ = Configuration::locateConfigFile(appRoot_);
configuration_ = new Configuration(application_, appRoot_,
configurationFile_, this);
}
return *configuration_;
}
bool WServer::readConfigurationProperty(const std::string& name,
std::string& value) const
{
WServer *self = const_cast<WServer *>(this);
return self->configuration().readConfigurationProperty(name, value);
}
void WServer::post(const std::string& sessionId,
const boost::function<void ()>& function,
const boost::function<void ()>& fallbackFunction)
{
schedule(0, sessionId, function, fallbackFunction);
}
void WServer::schedule(int milliSeconds,
const std::string& sessionId,
const boost::function<void ()>& function,
const boost::function<void ()>& fallbackFunction)
{
ApplicationEvent event(sessionId, function, fallbackFunction);
ioService().schedule(milliSeconds,
boost::bind(&WebController::handleApplicationEvent,
webController_, event));
}
void WServer::addEntryPoint(EntryPointType type, ApplicationCreator callback,
const std::string& path, const std::string& favicon)
{
if (!path.empty() && !boost::starts_with(path, "/"))
throw WServer::Exception("WServer::addEntryPoint() error: "
"deployment path should start with \'/\'");
configuration().addEntryPoint(EntryPoint(type, callback, path, favicon));
}
void WServer::addResource(WResource *resource, const std::string& path)
{
if (!boost::starts_with(path, "/"))
throw WServer::Exception("WServer::addResource() error: "
"static resource path should start with \'/\'");
resource->setInternalPath(path);
configuration().addEntryPoint(EntryPoint(resource, path));
}
void WServer::restart(int argc, char **argv, char **envp)
{
#ifndef WIN32
char *path = realpath(argv[0], 0);
// Try a few times since this may fail because we have an incomplete
// binary...
for (int i = 0; i < 5; ++i) {
int result = execve(path, argv, envp);
if (result != 0)
sleep(1);
}
perror("execve");
#endif
}
void WServer::setCatchSignals(bool catchSignals)
{
CatchSignals = catchSignals;
}
#if defined(_WIN32) && defined(WT_THREADED)
boost::mutex terminationMutex;
bool terminationRequested = false;
boost::condition terminationCondition;
BOOL WINAPI console_ctrl_handler(DWORD ctrl_type)
{
switch (ctrl_type)
{
case CTRL_C_EVENT:
case CTRL_BREAK_EVENT:
case CTRL_CLOSE_EVENT:
case CTRL_SHUTDOWN_EVENT:
{
boost::mutex::scoped_lock terminationLock(terminationMutex);
terminationRequested = true;
terminationCondition.notify_all(); // should be just 1
return TRUE;
}
default:
return FALSE;
}
}
#endif
int WServer::waitForShutdown(const char *restartWatchFile)
{
#if !defined(WIN32)
if (!CatchSignals) {
for(;;)
sleep(0x1<<16);
}
#endif // WIN32
#ifdef WT_THREADED
#if !defined(_WIN32)
sigset_t wait_mask;
sigemptyset(&wait_mask);
// Block the signals which interest us
sigaddset(&wait_mask, SIGHUP);
sigaddset(&wait_mask, SIGINT);
sigaddset(&wait_mask, SIGQUIT);
sigaddset(&wait_mask, SIGTERM);
pthread_sigmask(SIG_BLOCK, &wait_mask, 0);
for (;;) {
int rc, sig= -1;
// Wait for a signal to be raised
rc= sigwait(&wait_mask, &sig);
// branch based on return value of sigwait().
switch(rc) {
case 0: // rc indicates one of the blocked signals was raised.
// branch based on the signal which was raised.
switch(sig) {
case SIGHUP: // SIGHUP means re-read the configuration.
if (instance()) instance()->configuration().rereadConfiguration();
break;
default: // Any other blocked signal means time to quit.
return sig;
}
break;
case EINTR: // rc indicates an unblocked signal was raised, so we'll go around again.
break;
default: // report the error and return an obviously illegitimate signal value.
throw WServer::Exception(std::string("sigwait() error: ") + strerror(rc));
return -1;
}
}
#else // WIN32
boost::mutex::scoped_lock terminationLock(terminationMutex);
SetConsoleCtrlHandler(console_ctrl_handler, TRUE);
while (!terminationRequested)
terminationCondition.wait(terminationLock);
SetConsoleCtrlHandler(console_ctrl_handler, FALSE);
return 0;
#endif // WIN32
#else
return 0;
#endif // WT_THREADED
}
void WServer::expireSessions()
{
webController_->expireSessions();
}
}
------------------------------------------------------------------------------
Ridiculously easy VDI. With Citrix VDI-in-a-Box, you don't need a complex
infrastructure or vast IT resources to deliver seamless, secure access to
virtual desktops. With this all-in-one solution, easily deploy virtual
desktops for less than the cost of PCs and save 60% on VDI infrastructure
costs. Try it free! http://p.sf.net/sfu/Citrix-VDIinabox
_______________________________________________
witty-interest mailing list
witty-interest@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/witty-interest