- nhttp: enable threading

This is ported from neutrino-mp and contains code by martii and seife
from following commits:
20d3031b8bb47b5af79bf10c385e3564fe5c26dc
93d01c1987
363633dc1b
c3e1310a2f727e26ce11669e3aeae78305f87049
This commit is contained in:
svenhoefer
2014-08-19 13:13:31 +02:00
committed by [CST] Focus
parent f9c7662c73
commit 7589a3a9e0
5 changed files with 50 additions and 32 deletions

View File

@@ -144,8 +144,6 @@ void * timerd_main_thread(void *data);
static bool timerd_thread_started = false; static bool timerd_thread_started = false;
void * nhttpd_main_thread(void *data); void * nhttpd_main_thread(void *data);
static pthread_t nhttpd_thread ;
static bool nhttpd_thread_started = false;
//#define DISABLE_SECTIONSD //#define DISABLE_SECTIONSD
@@ -1955,8 +1953,9 @@ TIMER_START();
dvbsub_init(); dvbsub_init();
pthread_create (&nhttpd_thread, NULL, nhttpd_main_thread, (void *) NULL); pthread_t nhttpd_thread;
nhttpd_thread_started = true; if (!pthread_create (&nhttpd_thread, NULL, nhttpd_main_thread, (void *) NULL))
pthread_detach (nhttpd_thread);
CStreamManager::getInstance()->Start(); CStreamManager::getInstance()->Start();
@@ -3793,12 +3792,6 @@ void stop_daemons(bool stopall, bool for_flash)
delete g_Radiotext; delete g_Radiotext;
g_Radiotext = NULL; g_Radiotext = NULL;
} }
printf("httpd shutdown\n");
if (nhttpd_thread_started) {
pthread_cancel(nhttpd_thread);
pthread_join(nhttpd_thread, NULL);
}
printf("httpd shutdown done\n");
printf("streaming shutdown\n"); printf("streaming shutdown\n");
CStreamManager::getInstance()->Stop(); CStreamManager::getInstance()->Stop();
printf("streaming shutdown done\n"); printf("streaming shutdown done\n");

View File

@@ -61,14 +61,15 @@
#define Y_CONFIG_FEATUE_SENDFILE_CAN_ACCESS_ALL y // Add Feature: every file can be accessed (use carefully: security!!) #define Y_CONFIG_FEATUE_SENDFILE_CAN_ACCESS_ALL y // Add Feature: every file can be accessed (use carefully: security!!)
//#define Y_CONFIG_FEATURE_CHROOT y // Add Feature: Use Change Root for Security //#define Y_CONFIG_FEATURE_CHROOT y // Add Feature: Use Change Root for Security
//#define Y_CONFIG_FEATURE_HTTPD_USER y // Add Feature: Set User for yhttpd-Process //#define Y_CONFIG_FEATURE_HTTPD_USER y // Add Feature: Set User for yhttpd-Process
#define Y_CONFIG_BUILD_AS_DAEMON y // Build as a Daemon with possibility for multi threading #define Y_CONFIG_BUILD_AS_DAEMON y // Build as a Daemon
#define Y_CONFIG_FEATURE_THREADING y // Build with possibility for multi threading
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Define/Undefine Features forced by CONFIG_SYSTEM_xxx // Define/Undefine Features forced by CONFIG_SYSTEM_xxx
// Dependencies // Dependencies
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#ifdef Y_CONFIG_USE_OPEN_SSL //#ifdef Y_CONFIG_USE_OPEN_SSL
#undef Y_CONFIG_HAVE_SENDFILE // Sendfile does not work for SSL //#undef Y_CONFIG_HAVE_SENDFILE // Sendfile does not work for SSL, but we'll fallback to send
#endif //#endif
#if defined(CONFIG_SYSTEM_TUXBOX) || defined(CONFIG_SYSTEM_TUXBOX_COOLSTREAM) #if defined(CONFIG_SYSTEM_TUXBOX) || defined(CONFIG_SYSTEM_TUXBOX_COOLSTREAM)
#define Y_CONFIG_FEATURE_UPLOAD y #define Y_CONFIG_FEATURE_UPLOAD y

View File

@@ -12,6 +12,7 @@
#include <syscall.h> #include <syscall.h>
#include <stdio.h> #include <stdio.h>
#include <system/set_threadname.h>
// yhttpd // yhttpd
#include "yconfig.h" #include "yconfig.h"
#include <ylogging.h> #include <ylogging.h>
@@ -105,9 +106,22 @@ void yhttpd_reload_config() {
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Main Entry // Main Entry
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void thread_cleanup (void *p)
{
Cyhttpd *y = (Cyhttpd *)p;
if (y) {
y->stop_webserver();
delete y;
}
y = NULL;
}
#ifndef Y_CONFIG_BUILD_AS_DAEMON #ifndef Y_CONFIG_BUILD_AS_DAEMON
void * nhttpd_main_thread(void *) { void * nhttpd_main_thread(void *) {
set_threadname(__func__);
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, 0); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, 0);
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
aprintf("Webserver %s tid %ld\n", WEBSERVERNAME, syscall(__NR_gettid)); aprintf("Webserver %s tid %ld\n", WEBSERVERNAME, syscall(__NR_gettid));
yhttpd = new Cyhttpd(); yhttpd = new Cyhttpd();
//CLogging::getInstance()->setDebug(true); //CLogging::getInstance()->setDebug(true);
@@ -116,7 +130,11 @@ void * nhttpd_main_thread(void *) {
aprintf("Error initializing WebServer\n"); aprintf("Error initializing WebServer\n");
return (void *) EXIT_FAILURE; return (void *) EXIT_FAILURE;
} }
/* we pthread_cancel this thread from the main thread, but still want to clean up */
pthread_cleanup_push(thread_cleanup, yhttpd);
#ifndef Y_CONFIG_FEATURE_THREADING
yhttpd->flag_threading_off = true; yhttpd->flag_threading_off = true;
#endif
yhttpd->hooks_attach(); yhttpd->hooks_attach();
yhttpd->ReadConfig(); yhttpd->ReadConfig();
@@ -127,7 +145,9 @@ void * nhttpd_main_thread(void *) {
yhttpd->run(); yhttpd->run();
} }
pthread_cleanup_pop(0);
delete yhttpd; delete yhttpd;
yhttpd = NULL;
aprintf("Main end\n"); aprintf("Main end\n");
return (void *) EXIT_SUCCESS; return (void *) EXIT_SUCCESS;
@@ -235,6 +255,7 @@ Cyhttpd::Cyhttpd() {
Cyhttpd::~Cyhttpd() { Cyhttpd::~Cyhttpd() {
if (webserver) if (webserver)
delete webserver; delete webserver;
CLanguage::deleteInstance();
webserver = NULL; webserver = NULL;
} }
@@ -316,6 +337,7 @@ bool Cyhttpd::Configure() {
// Main Webserver call // Main Webserver call
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void Cyhttpd::run() { void Cyhttpd::run() {
set_threadname(__func__);
if (webserver) { if (webserver) {
if (flag_threading_off) if (flag_threading_off)
webserver->is_threading = false; webserver->is_threading = false;
@@ -439,7 +461,7 @@ void Cyhttpd::ReadConfig(void) {
log_level_printf(3, "ReadConfig Start\n"); log_level_printf(3, "ReadConfig Start\n");
CConfigFile *Config = new CConfigFile(','); CConfigFile *Config = new CConfigFile(',');
bool have_config = false; bool have_config = false;
if (access(HTTPD_CONFIGFILE, 4) == 0) if (access(HTTPD_CONFIGFILE, R_OK) == 0)
have_config = true; have_config = true;
Config->loadConfig(HTTPD_CONFIGFILE); Config->loadConfig(HTTPD_CONFIGFILE);
// convert old config files // convert old config files
@@ -527,16 +549,16 @@ void Cyhttpd::ReadConfig(void) {
// Check location of logos // Check location of logos
if (Config->getString("Tuxbox.LogosURL", "") == "") { if (Config->getString("Tuxbox.LogosURL", "") == "") {
if (access(std::string(ConfigList["WebsiteMain.override_directory"] + "/logos").c_str(), 4) == 0) { if (access(std::string(ConfigList["WebsiteMain.override_directory"] + "/logos").c_str(), R_OK) == 0) {
Config->setString("Tuxbox.LogosURL", ConfigList["WebsiteMain.override_directory"] + "/logos"); Config->setString("Tuxbox.LogosURL", ConfigList["WebsiteMain.override_directory"] + "/logos");
have_config = false; //save config have_config = false; //save config
} }
else if (access(std::string(ConfigList["WebsiteMain.directory"] + "/logos").c_str(), 4) == 0){ else if (access(std::string(ConfigList["WebsiteMain.directory"] + "/logos").c_str(), R_OK) == 0) {
Config->setString("Tuxbox.LogosURL", ConfigList["WebsiteMain.directory"] + "/logos"); Config->setString("Tuxbox.LogosURL", ConfigList["WebsiteMain.directory"] + "/logos");
have_config = false; //save config have_config = false; //save config
} }
#ifdef Y_CONFIG_USE_HOSTEDWEB #ifdef Y_CONFIG_USE_HOSTEDWEB
else if (access(std::string(ConfigList["WebsiteMain.hosted_directory"] + "/logos").c_str(), 4) == 0){ else if (access(std::string(ConfigList["WebsiteMain.hosted_directory"] + "/logos").c_str(), R_OK) == 0) {
Config->setString("Tuxbox.LogosURL", ConfigList["WebsiteMain.hosted_directory"] + "/logos"); Config->setString("Tuxbox.LogosURL", ConfigList["WebsiteMain.hosted_directory"] + "/logos");
have_config = false; //save config have_config = false; //save config
} }

View File

@@ -229,7 +229,7 @@ bool CySocket::set_option(int typ, int option) {
void CySocket::set_reuse_port() { void CySocket::set_reuse_port() {
#ifdef SO_REUSEPORT #ifdef SO_REUSEPORT
if(!set_option(SOL_SOCKET, SO_REUSEPORT)) if(!set_option(SOL_SOCKET, SO_REUSEPORT))
dperror("setsockopt(SO_REUSEPORT)\n"); dperror("setsockopt(SO_REUSEPORT)\n");
#endif #endif
} }
@@ -239,7 +239,7 @@ void CySocket::set_reuse_port() {
void CySocket::set_reuse_addr() { void CySocket::set_reuse_addr() {
#ifdef SO_REUSEADDR #ifdef SO_REUSEADDR
if(!set_option(SOL_SOCKET, SO_REUSEADDR)) if(!set_option(SOL_SOCKET, SO_REUSEADDR))
dperror("setsockopt(SO_REUSEADDR)\n"); dperror("setsockopt(SO_REUSEADDR)\n");
#endif #endif
} }
@@ -249,7 +249,7 @@ void CySocket::set_reuse_addr() {
void CySocket::set_keep_alive() { void CySocket::set_keep_alive() {
#ifdef SO_KEEPALIVE #ifdef SO_KEEPALIVE
if(!set_option(SOL_SOCKET, SO_KEEPALIVE)) if(!set_option(SOL_SOCKET, SO_KEEPALIVE))
dperror("setsockopt(SO_KEEPALIVE)\n"); dperror("setsockopt(SO_KEEPALIVE)\n");
#endif #endif
} }
@@ -259,7 +259,7 @@ void CySocket::set_keep_alive() {
void CySocket::set_tcp_nodelay() { void CySocket::set_tcp_nodelay() {
#ifdef TCP_NODELAY #ifdef TCP_NODELAY
if(!set_option(IPPROTO_TCP, TCP_NODELAY)) if(!set_option(IPPROTO_TCP, TCP_NODELAY))
dperror("setsockopt(SO_KEEPALIVE)\n"); dperror("setsockopt(SO_KEEPALIVE)\n");
#endif #endif
} }
//============================================================================= //=============================================================================
@@ -271,10 +271,10 @@ void CySocket::set_tcp_nodelay() {
int CySocket::Read(char *buffer, unsigned int length) { int CySocket::Read(char *buffer, unsigned int length) {
#ifdef Y_CONFIG_USE_OPEN_SSL #ifdef Y_CONFIG_USE_OPEN_SSL
if(isSSLSocket) if(isSSLSocket)
return SSL_read(ssl, buffer, length); return SSL_read(ssl, buffer, length);
else else
#endif #endif
return ::read(sock, buffer, length); return ::read(sock, buffer, length);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Send a buffer (normal or SSL) // Send a buffer (normal or SSL)
@@ -283,7 +283,7 @@ int CySocket::Send(char const *buffer, unsigned int length) {
unsigned int len = 0; unsigned int len = 0;
#ifdef Y_CONFIG_USE_OPEN_SSL #ifdef Y_CONFIG_USE_OPEN_SSL
if(isSSLSocket) if(isSSLSocket)
len = SSL_write(ssl, buffer, length); len = SSL_write(ssl, buffer, length);
else else
#endif #endif
len = ::send(sock, buffer, length, MSG_NOSIGNAL); len = ::send(sock, buffer, length, MSG_NOSIGNAL);
@@ -323,6 +323,9 @@ bool CySocket::SendFile(int filed, off_t start, off_t size) {
if (size > -1 && size < left) if (size > -1 && size < left)
left = size; left = size;
#ifdef Y_CONFIG_HAVE_SENDFILE #ifdef Y_CONFIG_HAVE_SENDFILE
#ifdef Y_CONFIG_USE_OPEN_SSL
if(!isSSLSocket)
#endif
while (left > 0) { while (left > 0) {
// split sendfile() transfer to smaller chunks to reduce memory-mapping requirements // split sendfile() transfer to smaller chunks to reduce memory-mapping requirements
if((written = ::sendfile(sock, filed, &start, std::min((off_t) 0x8000000LL, left))) == -1) { if((written = ::sendfile(sock, filed, &start, std::min((off_t) 0x8000000LL, left))) == -1) {
@@ -334,7 +337,7 @@ bool CySocket::SendFile(int filed, off_t start, off_t size) {
} else { } else {
BytesSend += written; BytesSend += written;
left -= written; left -= written;
} }
} }
#endif // Y_CONFIG_HAVE_SENDFILE #endif // Y_CONFIG_HAVE_SENDFILE
if (left > 0) { if (left > 0) {
@@ -347,7 +350,6 @@ bool CySocket::SendFile(int filed, off_t start, off_t size) {
perror("send failed"); perror("send failed");
return false; return false;
} }
BytesSend += written;
left -= written; left -= written;
} }
} }
@@ -372,7 +374,7 @@ unsigned int CySocket::ReceiveFileGivenLength(int filed, unsigned int _length) {
u_long readarg = 0; u_long readarg = 0;
#ifdef Y_CONFIG_USE_OPEN_SSL #ifdef Y_CONFIG_USE_OPEN_SSL
if(isSSLSocket) if(isSSLSocket)
readarg = RECEIVE_BLOCK_LEN; readarg = RECEIVE_BLOCK_LEN;
else else
#endif #endif
{ {

View File

@@ -48,7 +48,7 @@ CWebserver::CWebserver() {
FD_ZERO(&read_fds); FD_ZERO(&read_fds);
fdmax = 0; fdmax = 0;
open_connections = 0; open_connections = 0;
#ifdef Y_CONFIG_BUILD_AS_DAEMON #ifdef Y_CONFIG_FEATURE_THREADING
pthread_attr_init(&attr); pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
#endif #endif
@@ -412,13 +412,13 @@ bool CWebserver::handle_connection(CySocket *newSock) {
newConn->ySock = newSock; newConn->ySock = newSock;
newConn->ySock->handling = true; newConn->ySock->handling = true;
newConn->WebserverBackref = this; newConn->WebserverBackref = this;
#ifdef Y_CONFIG_BUILD_AS_DAEMON #ifdef Y_CONFIG_FEATURE_THREADING
newConn->is_treaded = is_threading; newConn->is_treaded = is_threading;
#else #else
newConn->is_treaded = false; newConn->is_treaded = false;
#endif #endif
int index = -1; int index = -1;
#ifdef Y_CONFIG_BUILD_AS_DAEMON #ifdef Y_CONFIG_FEATURE_THREADING
if(is_threading) if(is_threading)
{ {
pthread_mutex_lock( &mutex ); pthread_mutex_lock( &mutex );
@@ -442,7 +442,7 @@ bool CWebserver::handle_connection(CySocket *newSock) {
// start connection Thread // start connection Thread
if(pthread_create(&Connection_Thread_List[index], &attr, WebThread, (void *)newConn) != 0) if(pthread_create(&Connection_Thread_List[index], &attr, WebThread, (void *)newConn) != 0)
dperror("Could not create Connection-Thread\n"); dperror("Could not create Connection-Thread\n");
} }
else // non threaded else // non threaded
#endif #endif