1
0
mirror of https://github.com/stefanocasazza/ULib.git synced 2025-09-28 19:05:55 +08:00

bug fixing

This commit is contained in:
stefanocasazza 2015-07-20 19:04:46 +02:00
parent 9ac5de60a3
commit 8f3c28a7e7
34 changed files with 1232 additions and 944 deletions

5
configure vendored
View File

@ -24472,7 +24472,10 @@ $as_echo "$msg" >&6; }
$as_echo "#define USE_LIBEXPAT 1" >>confdefs.h
expat_version=$(strings $expatdir/lib*/libexpat.* 2>/dev/null | grep "^expat_[0-9]" | head -n1 | cut -d'_' -f2)
expat_version=$(strings $expatdir/lib*/libexpat.* 2>/dev/null | grep "^expat_[0-9]*" | head -n1 | cut -d'_' -f2)
if test -z "${expat_version}"; then
expat_version=$(ls $expatdir/libexpat.so.*.* 2>/dev/null | head -n 1 | awk -F'.so.' '{n=2; print $n}' 2>/dev/null)
fi
if test -z "${expat_version}"; then
expat_version="unknown"
fi

View File

@ -142,7 +142,7 @@ U_EXPORT void u_printSize(char* restrict buffer, uint64_t bytes); /* prin
U_EXPORT char* u_getPathRelativ(const char* restrict path, uint32_t* restrict path_len);
U_EXPORT bool u_rmatch(const char* restrict haystack, uint32_t haystack_len, const char* restrict needle, uint32_t needle_len) __pure;
U_EXPORT double u_calcRate(uint64_t bytes, uint32_t msecs, int* restrict units); /* Calculate the transfert rate */
U_EXPORT uint32_t u_findEndHeader( const char* restrict s, uint32_t n); /* find sequence of U_CRLF2 or U_LF2 */
U_EXPORT uint32_t u_findEndHeader( const char* restrict s, uint32_t n) __pure; /* find sequence of U_CRLF2 or U_LF2 */
U_EXPORT uint32_t u_findEndHeader1(const char* restrict s, uint32_t n) __pure; /* find sequence of U_CRLF2 */
U_EXPORT const char* u_get_mimetype(const char* restrict suffix, int* pmime_index);

View File

@ -1129,7 +1129,7 @@ public:
// Check equality with string at pos
bool isEqual(uint32_t pos, const UString& str, bool ignore_case = false);
bool isEqual(uint32_t pos, const UString& str, bool ignore_case = false) __pure;
// Check equality with an existing vector object

View File

@ -139,7 +139,7 @@ public:
{
U_TRACE(0, "UTimeDate::updateTime(%.5S)", ptr)
U_INTERNAL_ASSERT_DIFFERS(u_now->tv_sec % U_ONE_HOUR_IN_SECOND, 0)
U_INTERNAL_ASSERT(u_now->tv_sec % U_ONE_HOUR_IN_SECOND)
U_NUM2STR16(ptr, (u_now->tv_sec / 60) % 60);
U_NUM2STR16(ptr+3,u_now->tv_sec % 60);

View File

@ -1706,6 +1706,7 @@ static void usp_init_wi_auth()
file_RECOVERY = U_NEW(UFile(dir + U_STRING_FROM_CONSTANT("/wifi-recovery")));
file_UTILIZZO = U_NEW(UFile(dir + U_STRING_FROM_CONSTANT("/wifi-utilizzo")));
UServer_Base::update_date =
UServer_Base::update_date1 = true;
(void) UServer_Base::addLog(file_LOG);

View File

@ -35,15 +35,11 @@ class UClientImage_Base;
class U_EXPORT ULog : public UFile {
public:
typedef struct static_date {
struct timeval _timeval; // => u_now
char spinlock1[1];
typedef struct log_date {
char date1[17+1]; // 18/06/12 18:45:56
char spinlock2[1];
char date2[26+1]; // 04/Jun/2012:18:18:37 +0200
char spinlock3[1];
char date3[6+29+2+12+2+19+1]; // Date: Wed, 20 Jun 2012 11:43:17 GMT\r\nServer: ULib\r\nConnection: close\r\n
} static_date;
} log_date;
typedef struct log_data {
uint32_t file_ptr;
@ -55,9 +51,13 @@ public:
} log_data;
static ULog* pthis;
static log_date date;
static const char* prefix;
static struct iovec iov_vec[5];
static static_date* ptr_static_date;
static log_date* ptr_shared_date;
#ifdef ENABLE_THREAD
static pthread_rwlock_t* prwlock;
#endif
// COSTRUTTORI
@ -137,6 +137,8 @@ protected:
bool checkForLogRotateDataToWrite();
#endif
static long tv_sec_old_1, tv_sec_old_2, tv_sec_old_3;
void write(const struct iovec* iov, int n);
#ifdef USE_LIBZ
@ -145,27 +147,13 @@ protected:
static void close();
static void startup();
static void initStaticDate();
static void _updateStaticDate(char* ptr, int which);
static void initDate();
static void updateDate1();
static void updateDate2();
static void updateDate3();
static void logResponse(const UString& data, const char* name, const char* format, ...);
static void log(const struct iovec* iov, const char* name, const char* type, int ncount, const char* msg, uint32_t msg_len, const char* format, ...);
static void updateStaticDate(char* ptr, int which)
{
U_TRACE(0, "ULog::updateStaticDate(%p,%d)", ptr, which)
U_INTERNAL_ASSERT_POINTER(ptr)
U_INTERNAL_ASSERT_DIFFERS(ptr[0], '\0')
# ifdef ENABLE_THREAD
if (u_pthread_time == 0)
# endif
_updateStaticDate(ptr, which);
U_INTERNAL_DUMP("ptr_static_date->date1 = %.17S ptr_static_date->date2 = %.26S ptr_static_date->date3+6 = %.29S",
ptr_static_date->date1, ptr_static_date->date2, ptr_static_date->date3+6)
}
private:
static int decode(const char* name, uint32_t len, bool bfacility) __pure U_NO_EXPORT;

View File

@ -268,40 +268,27 @@ public:
sem_t lock_user1;
sem_t lock_user2;
sem_t lock_rdb_server;
# ifdef USE_LIBSSL
sem_t lock_ssl_session;
# if defined(ENABLE_THREAD) && !defined(OPENSSL_NO_OCSP) && defined(SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB)
sem_t lock_ocsp_staple;
# endif
# endif
sem_t lock_static_date;
sem_t lock_data_session;
sem_t lock_db_not_found;
char spinlock_user1[1];
char spinlock_user2[1];
char spinlock_rdb_server[1];
char spinlock_data_session[1];
char spinlock_db_not_found[1];
# ifdef USE_LIBSSL
sem_t lock_ssl_session;
char spinlock_ssl_session[1];
# if defined(ENABLE_THREAD) && !defined(OPENSSL_NO_OCSP) && defined(SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB)
sem_t lock_ocsp_staple;
char spinlock_ocsp_staple[1];
# endif
# endif
char spinlock_static_date[1];
char spinlock_data_session[1];
char spinlock_db_not_found[1];
# ifdef ENABLE_THREAD
/* typedef struct static_date {
struct timeval _timeval; // => u_now
char spinlock1[1];
char date1[17+1]; // 18/06/12 18:45:56
char spinlock2[1];
char date2[26+1]; // 04/Jun/2012:18:18:37 +0200
char spinlock3[1];
char date3[6+29+2+12+2+19+1]; // Date: Wed, 20 Jun 2012 11:43:17 GMT\r\nServer: ULib\r\nConnection: close\r\n
} static_date; */
ULog::static_date static_date;
# endif
// ------------------------------------------------------------------------------
# ifdef ENABLE_THREAD
pthread_rwlock_t rwlock;
struct timeval now_shared; // => u_now
ULog::log_date log_date_shared;
# endif
ULog::log_data log_data_shared;
// -> maybe unnamed array of char for gzip compression (log rotate)
// --------------------------------------------------------------------------------
@ -316,33 +303,23 @@ public:
#define U_LOCK_USER1 &(UServer_Base::ptr_shared_data->lock_user1)
#define U_LOCK_USER2 &(UServer_Base::ptr_shared_data->lock_user2)
#define U_LOCK_RDB_SERVER &(UServer_Base::ptr_shared_data->lock_rdb_server)
#define U_LOCK_STATIC_DATE &(UServer_Base::ptr_shared_data->lock_static_date)
#define U_LOCK_SSL_SESSION &(UServer_Base::ptr_shared_data->lock_ssl_session)
#define U_LOCK_DATA_SESSION &(UServer_Base::ptr_shared_data->lock_data_session)
#define U_LOCK_DB_NOT_FOUND &(UServer_Base::ptr_shared_data->lock_db_not_found)
#define U_SPINLOCK_USER1 UServer_Base::ptr_shared_data->spinlock_user1
#define U_SPINLOCK_USER2 UServer_Base::ptr_shared_data->spinlock_user2
#define U_SPINLOCK_RDB_SERVER UServer_Base::ptr_shared_data->spinlock_rdb_server
#define U_SPINLOCK_STATIC_DATE UServer_Base::ptr_shared_data->spinlock_static_date
#define U_SPINLOCK_SSL_SESSION UServer_Base::ptr_shared_data->spinlock_ssl_session
#define U_SPINLOCK_DATA_SESSION UServer_Base::ptr_shared_data->spinlock_data_session
#define U_SPINLOCK_DB_NOT_FOUND UServer_Base::ptr_shared_data->spinlock_db_not_found
#define U_HTTP_DATE1_SPINLOCK UServer_Base::ptr_static_date->spinlock1
#define U_HTTP_DATE1 ((char*)&(UServer_Base::ptr_static_date->date1[0]))
#define U_HTTP_DATE2_SPINLOCK UServer_Base::ptr_static_date->spinlock2
#define U_HTTP_DATE2 ((char*)&(UServer_Base::ptr_static_date->date2[0]))
#define U_HTTP_DATE3_SPINLOCK UServer_Base::ptr_static_date->spinlock3
#define U_HTTP_DATE3 ((char*)&(UServer_Base::ptr_static_date->date3[6]))
#define U_LOG_DATA_SHARED &(UServer_Base::ptr_shared_data->log_data_shared)
static pid_t pid;
static ULock* lock_user1;
static ULock* lock_user2;
static int preforked_num_kids; // keeping a pool of children and that they accept connections themselves
static shared_data* ptr_shared_data;
static ULog::static_date* ptr_static_date;
static uint32_t shared_data_add, map_size;
static bool update_date1, update_date2, update_date3;
static bool update_date, update_date1, update_date2, update_date3;
static void setLockUser1()
{

View File

@ -191,7 +191,7 @@ public:
U_RETURN(0);
}
uint32_t remain(const char* ptr) const
ptrdiff_t remain(const char* ptr) const
{
U_TRACE(0, "UStringRep::remain(%p)", ptr)
@ -329,7 +329,7 @@ public:
bool equal(const UStringRep* rep) const { return equal(rep->str, rep->_length); }
__pure bool equal(const char* s, uint32_t n) const
{
U_TRACE(0, "UStringRep::equal(%#.*S,%u)", n, s, n) // problem with sanitize address
U_TRACE(0, "UStringRep::equal(%#.*S,%u)", n, s, n)
U_CHECK_MEMORY
@ -1109,7 +1109,7 @@ public:
explicit UString(uint32_t n)
{
U_TRACE_REGISTER_OBJECT_WITHOUT_CHECK_MEMORY(0, UString, "%u", n) // problem with sanitize address
U_TRACE_REGISTER_OBJECT_WITHOUT_CHECK_MEMORY(0, UString, "%u", n)
rep = UStringRep::create(0U, n, 0);
@ -1379,7 +1379,7 @@ public:
UString& append(const char* s, uint32_t n)
{
U_TRACE(0, "UString::append(%.*S,%u)", n, s, n) // problem with sanitize address
U_TRACE(0, "UString::append(%.*S,%u)", n, s, n)
if (n)
{
@ -1656,7 +1656,7 @@ public:
char c_char(uint32_t pos) const { return rep->at(pos); }
char* c_pointer(uint32_t pos) const { return (char*)rep->c_pointer(pos); }
uint32_t remain( const char* ptr) const { return rep->remain(ptr); }
ptrdiff_t remain( const char* ptr) const { return rep->remain(ptr); }
__pure uint32_t distance(const char* ptr) const { return rep->distance(ptr); }
void setFromInode(uint64_t* p) { (void) replace((const char*)p, sizeof(uint64_t)); }

View File

@ -69,6 +69,22 @@ public:
(void) U_SYSCALL(pthread_mutex_unlock, "%p", mutex);
}
static bool initRwLock(pthread_rwlock_t* rwlock)
{
U_TRACE(1, "UThread::initRwLock(%p)", rwlock)
pthread_rwlockattr_t rwlockattr;
if (U_SYSCALL(pthread_rwlockattr_init, "%p", &rwlockattr) != 0 ||
U_SYSCALL(pthread_rwlockattr_setpshared, "%p,%d", &rwlockattr, PTHREAD_PROCESS_SHARED) != 0 ||
U_SYSCALL(pthread_rwlock_init, "%p,%p", rwlock, &rwlockattr) != 0)
{
U_RETURN(false);
}
U_RETURN(true);
}
static bool initIPC(pthread_mutex_t* mutex, pthread_cond_t* cond);
static void doIPC(pthread_mutex_t* mutex, pthread_cond_t* cond, vPF function, bool wait);
@ -179,7 +195,14 @@ protected:
static void sigHandler(int signo);
static void execHandler(UThread* th);
static void threadCleanup(UThread* th);
static void threadCleanup(UThread* th)
{
U_TRACE(0, "UThread::threadCleanup(%p)", th)
th->close();
}
// A special global function, getThread(), is provided to identify the thread object that represents the current
// execution context you are running under. This is sometimes needed to deliver signals to the correct thread

View File

@ -1,6 +1,6 @@
// source: https://github.com/tatsuhiro-t/nghttp2/ @ 76b3ba2, under the following license
/*
/**
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2013 Tatsuhiro Tsujikawa

View File

@ -17,11 +17,6 @@
#include <ulib/net/ipaddress.h>
#include <ulib/container/hash_map.h>
#define HTTP2_CONNECTION_UPGRADE \
"HTTP/1.1 101 Switching Protocols\r\n" \
"Connection: Upgrade\r\n" \
"Upgrade: h2c\r\n\r\n"
#define HTTP2_CONNECTION_PREFACE "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n" // (24 bytes)
class UHTTP;
@ -119,14 +114,11 @@ protected:
};
enum StreamState {
STREAM_STATE_RECV_PSUEDO_HEADERS = 0x001,
STREAM_STATE_RECV_HEADERS = 0x002,
STREAM_STATE_RECV_BODY = 0x004,
STREAM_STATE_REQ_PENDING = 0x008,
STREAM_STATE_SEND_HEADERS = 0x010,
STREAM_STATE_SEND_BODY = 0x020,
STREAM_STATE_END_STREAM = 0x040,
STREAM_STATE_HALF_CLOSED = 0x080
STREAM_STATE_IDLE = 0x000,
STREAM_STATE_RESERVED = 0x001,
STREAM_STATE_OPEN = 0x002,
STREAM_STATE_HALF_CLOSED = 0x004,
STREAM_STATE_CLOSED = 0x008
};
enum ConnectionState {
@ -146,22 +138,18 @@ protected:
};
struct Connection {
// headers
UHashMap<UString>* itable;
UHashMap<UString>* otable;
// streams
Stream open_streams[100];
// settings
Settings peer_settings;
ConnectionState state; // state
Settings peer_settings; // settings
UHashMap<UString> itable; // headers request
// internal
uint32_t input_window;
uint32_t output_window;
int32_t hpack_max_capacity; // the value set by SETTINGS_HEADER_TABLE_SIZE
// streams
int max_open_stream_id;
uint32_t num_responding_streams;
uint32_t max_processed_stream_id;
// internal
ConnectionState state;
uint32_t input_window;
uint32_t output_window;
int32_t hpack_max_capacity; // the value set by SETTINGS_HEADER_TABLE_SIZE
Stream streams[100];
};
struct HpackHeaderTableEntry {
@ -238,32 +226,25 @@ protected:
static int nerror;
static Stream* pStream;
static bool settings_ack;
static FrameHeader frame;
static void* pConnectionEnd;
static Connection* pConnection;
static const Settings settings;
static const char* upgrade_settings;
static const Settings SETTINGS_HOST;
static const Settings SETTINGS_DEFAULT;
static uint32_t hash_static_table[61];
static HpackHeaderTableEntry hpack_static_table[61];
// SERVICES
static void readFrame();
static void decodeFrame();
static void readFrame();
static void sendError();
static void manageData();
static void managePriority();
static void manageWindowUpdate();
static void setStream();
static void setConnection();
static void sendError(int err);
static void resetReadBuffer(uint32_t length);
static void manageHeaders();
static bool readBodyRequest();
static bool updateSetting(const char* ptr, uint32_t len);
static void decodeHeaders(const char* ptr, const char* endptr);
static bool manageHeaders(const char** ptr, const char** endptr);
#ifdef DEBUG
static const char* getFrameTypeDescription();
@ -317,8 +298,11 @@ protected:
static const HuffSym huff_sym_table[];
static const HuffDecode huff_decode_table[][16];
static uint32_t hpackDecodeInt( const unsigned char* src, const unsigned char* src_end, int32_t* pvalue, uint8_t prefix_max);
static uint32_t hpackDecodeString(const unsigned char* src, const unsigned char* src_end, UString* pvalue);
static uint32_t hpackDecodeString(const unsigned char* src, const unsigned char* src_end, UString* pvalue);
static uint32_t hpackEncodeString( unsigned char* dst, const char* src, uint32_t len);
static unsigned char* hpackEncodeInt( unsigned char* dst, uint32_t value, uint8_t prefix_max);
static uint32_t hpackDecodeInt( const unsigned char* src, const unsigned char* src_end, int32_t* pvalue, uint8_t prefix_max);
private:
friend class UHTTP;

View File

@ -30,10 +30,6 @@ typedef int (*verify_cb)(int,X509_STORE_CTX*); /* error callback */
# define U_STORE_FLAGS (X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL)
#endif
#ifdef USE_LIBUUID
# include <uuid/uuid.h>
#endif
#ifndef FNM_CASEFOLD
#define FNM_CASEFOLD FNM_IGNORECASE
#endif
@ -44,7 +40,7 @@ typedef int (*verify_cb)(int,X509_STORE_CTX*); /* error callback */
struct U_EXPORT UServices {
static bool isSetuidRoot(); // UID handling: are we setuid-root...
static bool isSetuidRoot(); // UID handling: check if we are setuid-root
static void closeStdInputOutput(); // move stdin and stdout to /dev/null
static int getDevNull(const char* file); // return open(/dev/null)
@ -171,22 +167,18 @@ struct U_EXPORT UServices {
static void generateDigest(int alg, uint32_t keylen, const UString& data, UString& output, int base64 = 0)
{ generateDigest(alg, keylen, (unsigned char*)U_STRING_TO_PARAM(data), output, base64); }
#ifdef USE_LIBUUID
// creat a new unique UUID value - 16 bytes (128 bits) long
// return from the binary representation a 36-byte string (plus tailing '\0') of the form 1b4e28ba-2fa1-11d2-883f-0016d3cca427
static uuid_t uuid; // typedef unsigned char uuid_t[16];
static UString getUUID();
#endif
static uint64_t getUniqUID();
static UString getUUID();
static uint64_t getUniqUID(); // creat a new unique UUID value - 8 bytes (64 bits) long
#ifdef USE_LIBSSL
/* setup OPENSSL standard certificate directory. The X509_STORE holds the tables etc for verification stuff.
A X509_STORE_CTX is used while validating a single certificate. The X509_STORE has X509_LOOKUPs for looking
up certs. The X509_STORE then calls a function to actually verify the certificate chain
*/
/**
* setup OPENSSL standard certificate directory. The X509_STORE holds the tables etc for verification stuff.
* A X509_STORE_CTX is used while validating a single certificate. The X509_STORE has X509_LOOKUPs for looking
* up certs. The X509_STORE then calls a function to actually verify the certificate chain
*/
static UString* CApath;
static X509_STORE* store;
@ -227,8 +219,8 @@ struct U_EXPORT UServices {
* passwd is the corresponsding password for the private key
*/
static UString getSignatureValue(int alg, const UString& data, const UString& pkey, const UString& passwd, int base64, ENGINE* e = 0);
static bool verifySignature( int alg, const UString& data, const UString& signature, const UString& pkey, ENGINE* e = 0);
static UString getSignatureValue(int alg, const UString& data, const UString& pkey, const UString& passwd, int base64, ENGINE* e = 0);
#endif
};

View File

@ -271,6 +271,7 @@ public:
static int handlerREAD();
static bool handlerCache();
static int manageRequest();
static int processRequest();
static void initDbNotFound();
static void setEndRequestProcessing();

View File

@ -361,7 +361,10 @@ AC_DEFUN([AC_CHECK_PACKAGE],[
echo "${T_MD}libexpat found in $expatdir${T_ME}"
USE_LIBEXPAT=yes
AC_DEFINE(USE_LIBEXPAT, 1, [Define if enable libexpat support])
expat_version=$(strings $expatdir/lib*/libexpat.* 2>/dev/null | grep "^expat_[[0-9]]" | head -n1 | cut -d'_' -f2)
expat_version=$(strings $expatdir/lib*/libexpat.* 2>/dev/null | grep "^expat_[[0-9]]*" | head -n1 | cut -d'_' -f2)
if test -z "${expat_version}"; then
expat_version=$(ls $expatdir/libexpat.so.*.* 2>/dev/null | head -n 1 | awk -F'.so.' '{n=2; print $n}' 2>/dev/null)
fi
if test -z "${expat_version}"; then
expat_version="unknown"
fi

View File

@ -58,13 +58,14 @@ void u_debug_at_exit(void);
#ifdef HAVE_ENDIAN_H
# include <endian.h>
#endif
#ifdef HAVE_SYS_SYSCALL_H
# include <sys/syscall.h>
#endif
#ifndef _MSWINDOWS_
# include <pwd.h>
# include <sys/uio.h>
# include <sys/utsname.h>
#endif
/* For TIOCGWINSZ and friends: */
#ifdef HAVE_SYS_IOCTL_H
# include <sys/ioctl.h>
@ -386,14 +387,29 @@ bool u_setStartTime(void)
(void) gettimeofday(u_now, 0);
/*
/**
* The "hash seed" is a feature to perturb the results to avoid "algorithmic complexity attacks"
*
* http://lwn.net/Articles/474365
*/
u_seed_hash = u_random((uint32_t)u_pid ^ (uint32_t)u_now->tv_usec);
#ifdef SYS_getrandom
if (syscall(SYS_getrandom, &u_seed_hash, sizeof(u_seed_hash), 0) == sizeof(u_seed_hash)) u_seed_hash |= 1;
else
#endif
{
int fd = open("/dev/urandom", O_CLOEXEC | O_RDONLY);
if (fd < 0) fd = open("/dev/random", O_CLOEXEC | O_RDONLY);
if (fd > 0)
{
if (read(fd, &u_seed_hash, sizeof(u_seed_hash)) == sizeof(u_seed_hash)) u_seed_hash |= 1;
(void) close(fd);
}
}
/* seed the random generator */
u_set_seed_random(u_seed_hash >> 16, u_seed_hash % 4294967296);

View File

@ -582,7 +582,7 @@ __pure uint32_t u_findEndHeader1(const char* restrict str, uint32_t n)
/* find sequence of U_LF2 or U_CRLF2 */
uint32_t u_findEndHeader(const char* restrict str, uint32_t n)
__pure uint32_t u_findEndHeader(const char* restrict str, uint32_t n)
{
const char* restrict p;
const char* restrict end = str + n;

View File

@ -282,7 +282,7 @@ __pure uint32_t UVector<UString>::find(const UString& str, bool ignore_case)
// Check equality with string at pos
bool UVector<UString>::isEqual(uint32_t pos, const UString& str, bool ignore_case)
__pure bool UVector<UString>::isEqual(uint32_t pos, const UString& str, bool ignore_case)
{
U_TRACE(0, "UVector<UString>::isEqual(%u,%V,%b)", pos, str.rep, ignore_case)

View File

@ -34,18 +34,26 @@
#define U_MARK_END "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n" // 24
#define U_FMT_START_STOP "*** %s %N (%ubit, pid %P) [%U@%H] ***"
ULog* ULog::pthis;
const char* ULog::prefix;
struct iovec ULog::iov_vec[5];
ULog::static_date* ULog::ptr_static_date;
long ULog::tv_sec_old_1;
long ULog::tv_sec_old_2;
long ULog::tv_sec_old_3;
ULog* ULog::pthis;
const char* ULog::prefix;
struct iovec ULog::iov_vec[5];
ULog::log_date ULog::date;
ULog::log_date* ULog::ptr_shared_date;
#ifdef ENABLE_THREAD
pthread_rwlock_t* ULog::prwlock;
#endif
ULog::ULog(const UString& path, uint32_t _size, const char* dir_log_gz) : UFile(path, 0)
{
U_TRACE_REGISTER_OBJECT(0, ULog, "%V,%u,%S", path.rep, _size, dir_log_gz)
lock = 0;
log_file_sz = log_gzip_sz = 0;
ptr_log_data = 0;
log_file_sz =
log_gzip_sz = 0;
U_Log_start_stop_msg(this) = false;
@ -74,16 +82,16 @@ ULog::ULog(const UString& path, uint32_t _size, const char* dir_log_gz) : UFile(
return;
}
/*
typedef struct log_data {
uint32_t file_ptr;
uint32_t file_page;
uint32_t gzip_len;
sem_t lock_shared;
char spinlock_shared[1];
// --------------> maybe unnamed array of char for gzip compression...
} log_data;
*/
/**
* typedef struct log_data {
* uint32_t file_ptr;
* uint32_t file_page;
* uint32_t gzip_len;
* sem_t lock_shared;
* char spinlock_shared[1];
* // --------------> maybe unnamed array of char for gzip compression...
* } log_data;
*/
ptr_log_data = U_MALLOC_TYPE(log_data);
@ -186,38 +194,30 @@ ULog::~ULog()
#endif
}
void ULog::initStaticDate()
void ULog::initDate()
{
U_TRACE(1, "ULog::initStaticDate()")
U_INTERNAL_ASSERT_EQUALS(ptr_static_date, 0)
ptr_static_date = U_MALLOC_TYPE(static_date);
(void) U_SYSCALL(memset, "%p,%d,%u", ptr_static_date, 0, sizeof(static_date));
u_now = &(ptr_static_date->_timeval);
U_TRACE(1, "ULog::initDate()")
iov_vec[0].iov_len = 17;
iov_vec[1].iov_len =
iov_vec[4].iov_len = 1;
iov_vec[0].iov_base = (caddr_t) ptr_static_date->date1;
iov_vec[1].iov_base = (caddr_t) " ";
iov_vec[2].iov_base = (caddr_t) u_buffer;
iov_vec[4].iov_base = (caddr_t) U_LF;
iov_vec[0].iov_base = (caddr_t)date.date1;
iov_vec[1].iov_base = (caddr_t)" ";
iov_vec[2].iov_base = (caddr_t)u_buffer;
iov_vec[4].iov_base = (caddr_t)U_LF;
(void) U_SYSCALL(gettimeofday, "%p,%p", u_now, 0);
(void) u_strftime2(ptr_static_date->date1, 17, "%d/%m/%y %T", u_now->tv_sec + u_now_adjust);
(void) u_strftime2(ptr_static_date->date2, 26, "%d/%b/%Y:%T %z", u_now->tv_sec + u_now_adjust);
(void) u_strftime2(ptr_static_date->date3, 6+29+2+12+2+17+2, "Date: %a, %d %b %Y %T GMT\r\nServer: ULib\r\nConnection: close\r\n", u_now->tv_sec);
(void) u_strftime2(date.date1, 17, "%d/%m/%y %T", u_now->tv_sec + u_now_adjust);
(void) u_strftime2(date.date2, 26, "%d/%b/%Y:%T %z", u_now->tv_sec + u_now_adjust);
(void) u_strftime2(date.date3, 6+29+2+12+2+17+2, "Date: %a, %d %b %Y %T GMT\r\nServer: ULib\r\nConnection: close\r\n", u_now->tv_sec);
}
void ULog::startup()
{
U_TRACE(1, "ULog::startup()")
initStaticDate();
initDate();
log(U_FMT_START_STOP, "STARTUP", sizeof(void*) * 8);
@ -267,101 +267,233 @@ void ULog::setPrefix(const char* _prefix)
}
}
void ULog::_updateStaticDate(char* ptr, int which)
void ULog::updateDate1()
{
U_TRACE(1, "ULog::_updateStaticDate(%p,%d)", ptr, which)
U_TRACE(1, "ULog::updateDate1()")
/**
* 18/06/12 18:45:56
* 012345678901234567890123456789
*/
#ifdef ENABLE_THREAD
if (u_pthread_time)
{
# if defined(U_LOG_ENABLE) && defined(USE_LIBZ)
(void) U_SYSCALL(pthread_rwlock_rdlock, "%p", prwlock);
# endif
if (tv_sec_old_1 != u_now->tv_sec)
{
long tv_sec = u_now->tv_sec;
U_INTERNAL_DUMP("tv_sec_old_1 = %lu u_now->tv_sec = %lu", tv_sec_old_1, tv_sec)
if ((tv_sec - tv_sec_old_1) != 1 ||
(tv_sec % U_ONE_HOUR_IN_SECOND) == 0)
{
tv_sec_old_1 = tv_sec;
U_MEMCPY(date.date1, ptr_shared_date->date1, 17);
}
else
{
++tv_sec_old_1;
u_put_unalignedp16(date.date1+12, U_MULTICHAR_CONSTANT16(ptr_shared_date->date1[12],ptr_shared_date->date1[13]));
u_put_unalignedp16(date.date1+12+3,U_MULTICHAR_CONSTANT16(ptr_shared_date->date1[15],ptr_shared_date->date1[16]));
}
U_INTERNAL_ASSERT_EQUALS(tv_sec, tv_sec_old_1)
}
# if defined(U_LOG_ENABLE) && defined(USE_LIBZ)
(void) U_SYSCALL(pthread_rwlock_unlock, "%p", prwlock);
# endif
}
else
#endif
{
U_INTERNAL_ASSERT_EQUALS(u_pthread_time, 0)
(void) U_SYSCALL(gettimeofday, "%p,%p", u_now, 0);
bool bchange = ((u_now->tv_sec % U_ONE_HOUR_IN_SECOND) == 0);
if (which == 1)
if (tv_sec_old_1 != u_now->tv_sec)
{
static long tv_sec_old_1;
long tv_sec = u_now->tv_sec;
/**
* 18/06/12 18:45:56
* 012345678901234567890123456789
*/
U_INTERNAL_DUMP("tv_sec_old_1 = %lu u_now->tv_sec = %lu", tv_sec_old_1, tv_sec)
if (tv_sec_old_1 == u_now->tv_sec) return;
U_INTERNAL_ASSERT_MINOR(tv_sec_old_1, u_now->tv_sec)
if (bchange ||
(u_now->tv_sec - tv_sec_old_1) != 1)
if ((tv_sec - tv_sec_old_1) != 1 ||
(tv_sec % U_ONE_HOUR_IN_SECOND) == 0)
{
(void) u_strftime2(ptr, 17, "%d/%m/%y %T", (tv_sec_old_1 = u_now->tv_sec) + u_now_adjust);
(void) u_strftime2(date.date1, 17, "%d/%m/%y %T", (tv_sec_old_1 = tv_sec) + u_now_adjust);
}
else
{
++tv_sec_old_1;
UTimeDate::updateTime(ptr+12);
UTimeDate::updateTime(date.date1+12);
}
U_INTERNAL_ASSERT_EQUALS(u_now->tv_sec, tv_sec_old_1)
U_INTERNAL_ASSERT_EQUALS(tv_sec, tv_sec_old_1)
}
else if (which == 3)
}
U_INTERNAL_DUMP("date.date1 = %.17S", date.date1)
}
void ULog::updateDate2()
{
U_TRACE(1, "ULog::updateDate2()")
/**
* 04/Jun/2012:18:18:37 +0200
* 012345678901234567890123456789
*/
#ifdef ENABLE_THREAD
if (u_pthread_time)
{
static long tv_sec_old_3;
# if defined(U_LOG_ENABLE) && defined(USE_LIBZ)
(void) U_SYSCALL(pthread_rwlock_rdlock, "%p", prwlock);
# endif
/**
* Date: Wed, 20 Jun 2012 11:43:17 GMT\r\nServer: ULib\r\n
* 0123456789012345678901234567890123456789
*/
if (tv_sec_old_3 == u_now->tv_sec) return;
U_INTERNAL_ASSERT_MINOR(tv_sec_old_3, u_now->tv_sec)
if (bchange ||
(u_now->tv_sec - tv_sec_old_3) != 1)
if (tv_sec_old_2 != u_now->tv_sec)
{
(void) u_strftime2(ptr, 29-4, "%a, %d %b %Y %T", (tv_sec_old_3 = u_now->tv_sec)); // GMT can't change...
long tv_sec = u_now->tv_sec;
U_INTERNAL_DUMP("tv_sec_old_2 = %lu u_now->tv_sec = %lu", tv_sec_old_2, tv_sec)
if ((tv_sec - tv_sec_old_2) != 1 ||
(tv_sec % U_ONE_HOUR_IN_SECOND) == 0)
{
tv_sec_old_2 = tv_sec;
U_MEMCPY(date.date2, ptr_shared_date->date2, 26);
}
else
{
++tv_sec_old_2;
u_put_unalignedp16(date.date2+15, U_MULTICHAR_CONSTANT16(ptr_shared_date->date2[15],ptr_shared_date->date2[16]));
u_put_unalignedp16(date.date2+15+3,U_MULTICHAR_CONSTANT16(ptr_shared_date->date2[18],ptr_shared_date->date2[19]));
}
U_INTERNAL_ASSERT_EQUALS(tv_sec, tv_sec_old_2)
}
# if defined(U_LOG_ENABLE) && defined(USE_LIBZ)
(void) U_SYSCALL(pthread_rwlock_unlock, "%p", prwlock);
# endif
}
else
#endif
{
U_INTERNAL_ASSERT_EQUALS(u_pthread_time, 0)
(void) U_SYSCALL(gettimeofday, "%p,%p", u_now, 0);
if (tv_sec_old_2 != u_now->tv_sec)
{
long tv_sec = u_now->tv_sec;
U_INTERNAL_DUMP("tv_sec_old_2 = %lu u_now->tv_sec = %lu", tv_sec_old_2, tv_sec)
if ((tv_sec - tv_sec_old_2) != 1 ||
(tv_sec % U_ONE_HOUR_IN_SECOND) == 0)
{
(void) u_strftime2(date.date2, 26-6, "%d/%b/%Y:%T", (tv_sec_old_2 = tv_sec) + u_now_adjust);
}
else
{
++tv_sec_old_2;
UTimeDate::updateTime(date.date2+15);
}
U_INTERNAL_ASSERT_EQUALS(tv_sec, tv_sec_old_2)
}
}
U_INTERNAL_DUMP("date.date2 = %.26S", date.date2)
}
void ULog::updateDate3()
{
U_TRACE(1, "ULog::updateDate3()")
/**
* Date: Wed, 20 Jun 2012 11:43:17 GMT\r\nServer: ULib\r\n
* 0123456789012345678901234567890123
* 0123456789012345678901234567890123456789
*/
#ifdef ENABLE_THREAD
if (u_pthread_time)
{
# if defined(U_LOG_ENABLE) && defined(USE_LIBZ)
(void) U_SYSCALL(pthread_rwlock_rdlock, "%p", prwlock);
# endif
if (tv_sec_old_3 != u_now->tv_sec)
{
long tv_sec = u_now->tv_sec;
U_INTERNAL_DUMP("tv_sec_old_3 = %lu u_now->tv_sec = %lu", tv_sec_old_3, tv_sec)
if ((tv_sec - tv_sec_old_3) != 1 ||
(tv_sec % U_ONE_HOUR_IN_SECOND) == 0)
{
tv_sec_old_3 = tv_sec;
U_MEMCPY(date.date3+6, ptr_shared_date->date3+6, 29-4);
}
else
{
++tv_sec_old_3;
u_put_unalignedp16(date.date3+26, U_MULTICHAR_CONSTANT16(ptr_shared_date->date3[26],ptr_shared_date->date3[27]));
u_put_unalignedp16(date.date3+26+3,U_MULTICHAR_CONSTANT16(ptr_shared_date->date3[29],ptr_shared_date->date3[30]));
}
U_INTERNAL_ASSERT_EQUALS(tv_sec, tv_sec_old_3)
}
# if defined(U_LOG_ENABLE) && defined(USE_LIBZ)
(void) U_SYSCALL(pthread_rwlock_unlock, "%p", prwlock);
# endif
}
else
#endif
{
U_INTERNAL_ASSERT_EQUALS(u_pthread_time, 0)
(void) U_SYSCALL(gettimeofday, "%p,%p", u_now, 0);
if (tv_sec_old_3 != u_now->tv_sec)
{
long tv_sec = u_now->tv_sec;
U_INTERNAL_DUMP("tv_sec_old_3 = %lu u_now->tv_sec = %lu", tv_sec_old_3, tv_sec)
if ((tv_sec - tv_sec_old_3) != 1 ||
(tv_sec % U_ONE_HOUR_IN_SECOND) == 0)
{
(void) u_strftime2(date.date3+6, 29-4, "%a, %d %b %Y %T", (tv_sec_old_3 = tv_sec)); // GMT can't change...
}
else
{
++tv_sec_old_3;
UTimeDate::updateTime(ptr+20);
UTimeDate::updateTime(date.date3+26);
}
U_INTERNAL_ASSERT_EQUALS(u_now->tv_sec, tv_sec_old_3)
U_INTERNAL_ASSERT_EQUALS(tv_sec, tv_sec_old_3)
}
else
{
static long tv_sec_old_2;
}
U_INTERNAL_ASSERT_EQUALS(which, 2)
/**
* 04/Jun/2012:18:18:37 +0200
* 012345678901234567890123456789
*/
if (tv_sec_old_2 == u_now->tv_sec) return;
U_INTERNAL_ASSERT_MINOR(tv_sec_old_2, u_now->tv_sec)
if (bchange ||
(u_now->tv_sec - tv_sec_old_2) != 1)
{
(void) u_strftime2(ptr, 26-6, "%d/%b/%Y:%T", (tv_sec_old_2 = u_now->tv_sec) + u_now_adjust);
}
else
{
++tv_sec_old_2;
UTimeDate::updateTime(ptr+15);
}
U_INTERNAL_ASSERT_EQUALS(u_now->tv_sec, tv_sec_old_2)
}
U_INTERNAL_ASSERT_EQUALS(ptr_static_date->date1, iov_vec[0].iov_base)
U_INTERNAL_DUMP("date.date3+6 = %.29S", date.date3+6)
}
void ULog::setShared(log_data* ptr, uint32_t _size, bool breference)
@ -559,7 +691,7 @@ void ULog::write(const char* msg, uint32_t len)
iov_vec[3].iov_len = len;
iov_vec[3].iov_base = (caddr_t) msg;
updateStaticDate(ptr_static_date->date1, 1);
updateDate1();
pthis->write(iov_vec, 5);
@ -606,7 +738,7 @@ void ULog::log(int _fd, const char* fmt, ...)
iov_vec[3].iov_len = len;
iov_vec[3].iov_base = (caddr_t)buffer;
updateStaticDate(ptr_static_date->date1, 1);
updateDate1();
(void) U_SYSCALL(writev, "%d,%p,%d", _fd, iov_vec, 5);
}

View File

@ -20,7 +20,7 @@
# include <ulib/utility/http2.h>
#endif
int UClientImage_Base::idx;
int UClientImage_Base::idx;
int UClientImage_Base::csfd;
int UClientImage_Base::iovcnt;
iPF UClientImage_Base::callerHandlerRead;
@ -129,8 +129,23 @@ UClientImage_Base::UClientImage_Base()
last_event = u_now->tv_sec;
pending_close = 0;
// NB: array are not pointers (virtual table can shift the address of 'this')...
if (UServer_Base::pClientImage == 0)
{
UServer_Base::pClientImage = this;
UServer_Base::eClientImage = this + UNotifier::max_connection;
U_INTERNAL_DUMP("UServer_Base::pClientImage = %p UServer_Base::eClientImage = %p UNotifier::max_connection = %u",
UServer_Base::pClientImage, UServer_Base::eClientImage, UNotifier::max_connection)
}
U_INTERNAL_DUMP("new T[%u]: elem %u of %u", UNotifier::max_connection, (this - UServer_Base::pClientImage), UNotifier::max_connection)
#ifndef U_HTTP2_DISABLE
connection = U_NEW(UHTTP2::Connection);
((UHTTP2::Connection*)connection)->itable.setIndexFunction(UHTTP2::setIndexStaticTable);
#endif
}
@ -160,19 +175,6 @@ void UClientImage_Base::set()
{
U_TRACE(0, "UClientImage_Base::set()")
// NB: array are not pointers (virtual table can shift the address of 'this')...
if (UServer_Base::pClientImage == 0)
{
UServer_Base::pClientImage = this;
UServer_Base::eClientImage = this + UNotifier::max_connection;
U_INTERNAL_DUMP("UServer_Base::pClientImage = %p UServer_Base::eClientImage = %p UNotifier::max_connection = %u",
UServer_Base::pClientImage, UServer_Base::eClientImage, UNotifier::max_connection)
}
U_INTERNAL_DUMP("new T[%u]: elem %u of %u", UNotifier::max_connection, (this - UServer_Base::pClientImage), UNotifier::max_connection)
U_INTERNAL_DUMP("this = %p socket = %p UEventFd::fd = %d", this, socket, UEventFd::fd)
U_INTERNAL_ASSERT_POINTER(socket)
@ -223,7 +225,7 @@ bool UClientImage_Base::check_memory()
{
U_TRACE(0, "UClientImage_Base::check_memory()")
U_INTERNAL_DUMP("u_check_memory_vector<T>: elem %u of %u", this - UServer_Base::pClientImage, UNotifier::max_connection)
U_INTERNAL_DUMP("u_check_memory_vector<T>: elem %u of %u", this-UServer_Base::pClientImage, UNotifier::max_connection)
U_INTERNAL_DUMP("this = %p socket = %p UEventFd::fd = %d", this, socket, UEventFd::fd)
@ -778,12 +780,27 @@ void UClientImage_Base::manageReadBufferResize(uint32_t n)
{
U_TRACE(0, "UClientImage_Base::manageReadBufferResize(%u)", n)
ptrdiff_t diff;
const char* ptr;
U_DUMP("U_ClientImage_pipeline = %b size_request = %u rbuffer->size() = %u rbuffer->capacity() = %u request->size() = %u rstart = %u",
U_ClientImage_pipeline, size_request, rbuffer->size(), rbuffer->capacity(), request->size(), rstart)
#ifndef U_HTTP2_DISABLE
if (U_http_version == '2')
{
if (rstart)
{
rbuffer->moveToBeginDataInBuffer(rstart);
rstart = 0;
}
UString::_reserve(*rbuffer, n);
return;
}
#endif
ptrdiff_t diff;
const char* ptr;
request->clear();
if (U_ClientImage_pipeline)
@ -811,8 +828,7 @@ next1:
UString::_reserve(*rbuffer, n);
if (U_http_method_type &&
U_http_version != '2')
if (U_http_method_type)
{
diff = rbuffer->data() - ptr;
next2:
@ -1447,9 +1463,9 @@ bool UClientImage_Base::writeResponse()
msg_len = (U_ClientImage_pipeline ? U_CONSTANT_SIZE("[pipeline] ") : 0);
iov_vec[2].iov_len = sz1;
iov_vec[2].iov_base = (caddr_t) wbuffer->data();
iov_vec[2].iov_base = (caddr_t)wbuffer->data();
iov_vec[3].iov_len = sz2;
iov_vec[3].iov_base = (caddr_t) body->data();
iov_vec[3].iov_base = (caddr_t)body->data();
ncount = sz1 + sz2;
@ -1478,7 +1494,14 @@ bool UClientImage_Base::writeResponse()
u__memcpy(iov_sav, iov_vec, U_IOV_TO_SAVE, __PRETTY_FUNCTION__);
ULog::updateStaticDate(UServer_Base::ptr_static_date->date3+6, 3);
# if defined(ENABLE_THREAD) && !defined(U_LOG_ENABLE) && !defined(USE_LIBZ)
U_INTERNAL_ASSERT_POINTER(u_pthread_time)
U_INTERNAL_ASSERT_EQUALS(iov_vec[1].iov_base, UServer_Base::ptr_shared_data->log_date_shared.date3)
# else
U_INTERNAL_ASSERT_EQUALS(iov_vec[1].iov_base, ULog::date.date3)
ULog::updateDate3();
# endif
# ifdef U_LOG_ENABLE
if (logbuf) ULog::log(iov_vec+idx, UServer_Base::mod_name[0], "response", ncount, "[pipeline] ", msg_len, " to %v", logbuf->rep);

View File

@ -348,6 +348,7 @@ int UHttpPlugIn::handlerConfig(UFileConfig& cfg)
if (x)
{
UServer_Base::update_date =
UServer_Base::update_date2 = true;
uint32_t size = cfg.readLong(*UString::str_LOG_FILE_SZ);
@ -446,11 +447,18 @@ int UHttpPlugIn::handlerRun() // NB: we use this method because now we have the
if (UServer_Base::vplugin_name->last() == *UString::str_http)
{
UServer_Base::update_date =
UServer_Base::update_date3 = true;
UClientImage_Base::iov_vec[1].iov_base = (caddr_t) UServer_Base::ptr_static_date->date3; // Date: Wed, 20 Jun 2012 11:43:17 GMT\r\nServer: ULib\r\n...
UClientImage_Base::iov_vec[1].iov_base = (caddr_t)ULog::date.date3; // Date: Wed, 20 Jun 2012 11:43:17 GMT\r\nServer: ULib\r\n...
UClientImage_Base::iov_vec[1].iov_len = 6+29+2+12+2+17+2;
# if defined(ENABLE_THREAD) && !defined(U_LOG_ENABLE) && !defined(USE_LIBZ)
U_INTERNAL_ASSERT_POINTER(u_pthread_time)
UClientImage_Base::iov_vec[1].iov_base = (caddr_t)UServer_Base::ptr_shared_data->log_date_shared.date3;
# endif
U_INTERNAL_DUMP("UClientImage_Base::iov_vec[0] = %.*S UClientImage_Base::iov_vec[1] = %.*S",
UClientImage_Base::iov_vec[0].iov_len, UClientImage_Base::iov_vec[0].iov_base,
UClientImage_Base::iov_vec[1].iov_len, UClientImage_Base::iov_vec[1].iov_base)

View File

@ -89,6 +89,7 @@ bool UServer_Base::public_address;
bool UServer_Base::monitoring_process;
bool UServer_Base::set_tcp_keep_alive;
bool UServer_Base::set_realtime_priority;
bool UServer_Base::update_date;
bool UServer_Base::update_date1;
bool UServer_Base::update_date2;
bool UServer_Base::update_date3;
@ -143,7 +144,6 @@ UVector<UString>* UServer_Base::vplugin_name_static;
UClientImage_Base* UServer_Base::pClientImage;
UClientImage_Base* UServer_Base::vClientImage;
UClientImage_Base* UServer_Base::eClientImage;
ULog::static_date* UServer_Base::ptr_static_date;
UVector<UServerPlugIn*>* UServer_Base::vplugin;
UServer_Base::shared_data* UServer_Base::ptr_shared_data;
UVector<UServer_Base::file_LOG*>* UServer_Base::vlog;
@ -167,24 +167,14 @@ UVector<UIPAllow*>* UServer_Base::vallow_IP_prv;
class UTimeThread : public UThread {
public:
UTimeThread() : UThread(true, false) { watch_counter = 1; }
#ifdef DEBUG
UTimeVal before;
#endif
int watch_counter;
UTimeThread() : UThread(true, false) {}
virtual void run()
{
U_TRACE(0, "UTimeThread::run()")
# ifdef DEBUG
long delta;
UTimeVal after;
# endif
bool bchange;
struct timespec ts;
long tv_sec_old = u_now->tv_sec;
u_timeval.tv_sec = u_now->tv_sec;
U_SRV_LOG("UTimeThread optimization for time resolution of one second activated (pid %u)", UThread::getTID());
@ -196,74 +186,46 @@ public:
(void) U_SYSCALL(nanosleep, "%p,%p", &ts, 0);
# if defined(U_LOG_ENABLE) && defined(USE_LIBZ)
if ((UServer_Base::log && UServer_Base::log->checkForLogRotateDataToWrite()) ||
(UServer_Base::apache_like_log && UServer_Base::apache_like_log->checkForLogRotateDataToWrite()))
{
watch_counter = 1;
}
if (UServer_Base::log) (void) UServer_Base::log->checkForLogRotateDataToWrite();
if (UServer_Base::apache_like_log) (void) UServer_Base::apache_like_log->checkForLogRotateDataToWrite();
# endif
U_INTERNAL_DUMP("watch_counter = %d tv_sec_old = %ld u_now->tv_sec = %ld", watch_counter, tv_sec_old, u_now->tv_sec)
U_INTERNAL_DUMP("u_timeval.tv_sec = %ld u_now->tv_sec = %ld", u_timeval.tv_sec, u_now->tv_sec)
if (tv_sec_old == u_now->tv_sec)
if (u_timeval.tv_sec == u_now->tv_sec)
{
if (--watch_counter > 0) u_now->tv_sec++;
(void) U_SYSCALL(gettimeofday, "%p,%p", u_now, 0);
if (u_timeval.tv_sec == u_now->tv_sec) continue;
}
U_INTERNAL_ASSERT_DIFFERS(u_now->tv_sec, u_timeval.tv_sec)
u_timeval.tv_sec = u_now->tv_sec;
if (UServer_Base::update_date)
{
# if defined(U_LOG_ENABLE) && defined(USE_LIBZ)
(void) U_SYSCALL(pthread_rwlock_wrlock, "%p", ULog::prwlock);
# endif
if ((u_timeval.tv_sec % U_ONE_HOUR_IN_SECOND) != 0)
{
if (UServer_Base::update_date1) UTimeDate::updateTime(ULog::ptr_shared_date->date1 + 12);
if (UServer_Base::update_date2) UTimeDate::updateTime(ULog::ptr_shared_date->date2 + 15);
if (UServer_Base::update_date3) UTimeDate::updateTime(ULog::ptr_shared_date->date3 + 26);
}
else
{
# ifdef DEBUG
if (watch_counter == 0)
{
before.tv_sec = u_now->tv_sec + 1;
before.tv_usec = u_now->tv_usec;
}
# endif
(void) U_SYSCALL(gettimeofday, "%p,%p", u_now, 0);
# ifdef DEBUG
after.set(*u_now);
after -= before;
delta = after.getMilliSecond();
if (delta >= 1000L ||
delta <= -1000L)
{
U_SRV_LOG("UTimeThread delta time exceed 1 sec: diff(%ld ms)", delta);
if (delta <= -30000L) U_ERROR("UTimeThread delta time exceed too much - ts = { %ld, %ld }", ts.tv_sec, ts.tv_nsec);
}
# endif
watch_counter = 30;
if (tv_sec_old == u_now->tv_sec) continue;
if (UServer_Base::update_date1) (void) u_strftime2(ULog::ptr_shared_date->date1, 17, "%d/%m/%y %T", u_timeval.tv_sec + u_now_adjust);
if (UServer_Base::update_date2) (void) u_strftime2(ULog::ptr_shared_date->date2, 26-6, "%d/%b/%Y:%T", u_timeval.tv_sec + u_now_adjust); // %z in general don't change...
if (UServer_Base::update_date3) (void) u_strftime2(ULog::ptr_shared_date->date3+6, 29-4, "%a, %d %b %Y %T", u_timeval.tv_sec); // GMT can't change...
}
# if defined(U_LOG_ENABLE) && defined(USE_LIBZ)
(void) U_SYSCALL(pthread_rwlock_unlock, "%p", ULog::prwlock);
# endif
}
U_INTERNAL_ASSERT_DIFFERS(u_now->tv_sec, tv_sec_old)
bchange = ((u_now->tv_sec % U_ONE_HOUR_IN_SECOND) == 0);
if (UServer_Base::update_date1)
{
if (bchange == false) UTimeDate::updateTime(U_HTTP_DATE1 + 12);
else (void) u_strftime2(U_HTTP_DATE1, 17, "%d/%m/%y %T", u_now->tv_sec + u_now_adjust);
}
if (UServer_Base::update_date2)
{
if (bchange == false) UTimeDate::updateTime(U_HTTP_DATE2 + 15);
else (void) u_strftime2(U_HTTP_DATE2, 26-6, "%d/%b/%Y:%T", u_now->tv_sec + u_now_adjust); // NB: %z in general don't change...
}
if (UServer_Base::update_date3)
{
if (bchange == false) UTimeDate::updateTime(U_HTTP_DATE3 + 20);
else (void) u_strftime2(U_HTTP_DATE3, 29-4, "%a, %d %b %Y %T", u_now->tv_sec); // GMT can't change...
}
tv_sec_old = u_now->tv_sec;
}
}
};
@ -395,9 +357,11 @@ UServer_Base::~UServer_Base()
((UTimeThread*)u_pthread_time)->suspend();
delete (UTimeThread*)u_pthread_time; // delete to join
(void) U_SYSCALL(pthread_rwlock_destroy, "%p", ULog::prwlock);
}
# if defined(USE_LIBSSL) && !defined(OPENSSL_NO_OCSP) && defined(SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB)
# if defined(USE_LIBSSL) && !defined(OPENSSL_NO_OCSP) && defined(SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB)
if (bssl)
{
if (pthread_ocsp)
@ -411,7 +375,7 @@ UServer_Base::~UServer_Base()
if (UServer_Base::lock_ocsp_staple) delete UServer_Base::lock_ocsp_staple;
}
# endif
# endif
#endif
UClientImage_Base::clear();
@ -876,6 +840,7 @@ void UServer_Base::loadConfigParam()
{
// open log
update_date =
update_date1 = true;
log = U_NEW(ULog(x, cfg->readLong(*UString::str_LOG_FILE_SZ)));
@ -1394,7 +1359,7 @@ void UServer_Base::init()
}
#else
/**
* This code does NOT make a connection or send any packets (to 64.233.187.99 which is google).
* This code does NOT make a connection or send any packets (to 8.8.8.8 which is google DNS).
* Since UDP is a stateless protocol connect() merely makes a system call which figures out how to
* route the packets based on the address and what interface (and therefore IP address) it should
* bind to. Returns an array containing the family (AF_INET), local port, and local address (which
@ -1545,7 +1510,7 @@ void UServer_Base::init()
#ifdef U_LOG_ENABLE
uint32_t log_rotate_size = 0;
# ifdef USE_LIBZ
# ifdef USE_LIBZ
if (isLog())
{
// The zlib documentation states that destination buffer size must be at least 0.1% larger than avail_in plus 12 bytes
@ -1553,7 +1518,7 @@ void UServer_Base::init()
log_rotate_size =
shared_data_add = log->UFile::st_size + (log->UFile::st_size / 10) + 12U;
}
# endif
# endif
U_INTERNAL_DUMP("log_rotate_size = %u", log_rotate_size)
#endif
@ -1585,61 +1550,56 @@ void UServer_Base::init()
#ifdef U_LOG_ENABLE
if (isLog() == false)
#endif
ULog::initStaticDate();
if (bpthread_time == false) ptr_static_date = ULog::ptr_static_date;
#ifdef ENABLE_THREAD
else
{
ptr_static_date = &(ptr_shared_data->static_date);
U_INTERNAL_ASSERT_POINTER( ULog::ptr_static_date)
U_INTERNAL_ASSERT_EQUALS((void*)u_now, (void*)ULog::ptr_static_date)
U_MEMCPY(ptr_static_date, ULog::ptr_static_date, sizeof(ULog::static_date));
u_now = &(ptr_static_date->_timeval);
ULog::iov_vec[0].iov_base = (caddr_t)ptr_static_date->date1;
U_FREE_TYPE(ULog::ptr_static_date, ULog::static_date);
ULog::ptr_static_date = ptr_static_date;
}
#endif
U_INTERNAL_ASSERT_EQUALS((void*)u_now, (void*)ptr_static_date)
U_INTERNAL_ASSERT_EQUALS((void*)u_now, (void*)ULog::ptr_static_date)
#if defined(ENABLE_THREAD) && !defined(_MSWINDOWS_)
// NB: we block SIGHUP and SIGTERM; the threads created will inherit a copy of the signal mask...
# ifdef sigemptyset
sigemptyset(&mask);
# else
(void) U_SYSCALL(sigemptyset, "%p", &mask);
# endif
# ifdef sigaddset
sigaddset(&mask, SIGHUP);
sigaddset(&mask, SIGTERM);
# else
(void) U_SYSCALL(sigaddset, "%p,%d", &mask, SIGHUP);
(void) U_SYSCALL(sigaddset, "%p,%d", &mask, SIGTERM);
# endif
(void) U_SYSCALL(pthread_sigmask, "%d,%p,%p", SIG_BLOCK, &mask, 0);
#endif
flag_loop = true; // NB: UTimeThread loop depend on this...
ULog::initDate();
#ifdef ENABLE_THREAD
if (bpthread_time)
{
U_INTERNAL_ASSERT_POINTER(ptr_shared_data)
U_INTERNAL_ASSERT_EQUALS(ULog::ptr_shared_date, 0)
u_now = &(ptr_shared_data->now_shared);
ULog::ptr_shared_date = &(ptr_shared_data->log_date_shared);
(void) U_SYSCALL(gettimeofday, "%p,%p", u_now, 0);
U_MEMCPY(ULog::ptr_shared_date, &ULog::date, sizeof(ULog::log_date));
}
#endif
#if defined(ENABLE_THREAD) && !defined(_MSWINDOWS_)
// NB: we block SIGHUP and SIGTERM; the threads created will inherit a copy of the signal mask...
# ifdef sigemptyset
sigemptyset(&mask);
# else
(void) U_SYSCALL(sigemptyset, "%p", &mask);
# endif
# ifdef sigaddset
sigaddset(&mask, SIGHUP);
sigaddset(&mask, SIGTERM);
# else
(void) U_SYSCALL(sigaddset, "%p,%d", &mask, SIGHUP);
(void) U_SYSCALL(sigaddset, "%p,%d", &mask, SIGTERM);
# endif
(void) U_SYSCALL(pthread_sigmask, "%d,%p,%p", SIG_BLOCK, &mask, 0);
#endif
flag_loop = true; // NB: UTimeThread loop depend on this setting...
#ifdef ENABLE_THREAD
if (bpthread_time)
{
U_INTERNAL_ASSERT_EQUALS(ULog::prwlock, 0)
U_INTERNAL_ASSERT_EQUALS(u_pthread_time, 0)
U_NEW_ULIB_OBJECT(u_pthread_time, UTimeThread);
U_INTERNAL_DUMP("u_pthread_time = %p", u_pthread_time)
(void) UThread::initRwLock((ULog::prwlock = &(ptr_shared_data->rwlock)));
((UTimeThread*)u_pthread_time)->start(50);
}
#endif
@ -1647,9 +1607,9 @@ void UServer_Base::init()
#ifdef U_LOG_ENABLE
if (isLog())
{
// NB: if log is mapped must be always shared cause of possibility of fork() by parallelization
// NB: if log is mapped must be always shared because of possibility of fork() by parallelization...
if (log->isMemoryMapped()) log->setShared(U_LOG_DATA_SHARED, log_rotate_size);
if (log->isMemoryMapped()) log->setShared(&(ptr_shared_data->log_data_shared), log_rotate_size);
U_SRV_LOG("Mapped %u bytes (%u KB) of shared memory for %d preforked process", sizeof(shared_data) + shared_data_add, map_size / 1024, preforked_num_kids);
}
@ -1690,8 +1650,8 @@ void UServer_Base::init()
/**
* There may not always be a connection waiting after a SIGIO is delivered or select(2) or poll(2) return a readability
* event because the connection might have been removed by an asynchronous network error or another thread before
* accept() is called. If this happens then the call will block waiting for the next connection to arrive. To ensure
* event because the connection might have been removed by an asynchronous network error or another thread before
* accept() is called. If this happens then the call will block waiting for the next connection to arrive. To ensure
* that accept() never blocks, the passed socket sockfd needs to have the O_NONBLOCK flag set (see socket(7))
*/
@ -1874,13 +1834,13 @@ RETSIGTYPE UServer_Base::handlerForSigHUP(int signo)
(void) U_SYSCALL(gettimeofday, "%p,%p", u_now, 0);
#ifdef ENABLE_THREAD
# if defined(USE_LIBSSL) && !defined(OPENSSL_NO_OCSP) && defined(SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB)
if (pthread_ocsp) pthread_ocsp->suspend();
# endif
# if defined(USE_LIBSSL) && !defined(OPENSSL_NO_OCSP) && defined(SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB)
if (pthread_ocsp) pthread_ocsp->suspend();
# endif
if (u_pthread_time) ((UTimeThread*)u_pthread_time)->suspend();
#endif
pthis->handlerSignal(); // manage before regenering preforked pool of children...
pthis->handlerSignal(); // manage signal before we regenering the preforked pool of children...
// NB: we can't use UInterrupt::erase() because it restore the old action (UInterrupt::init)...
@ -1896,19 +1856,9 @@ RETSIGTYPE UServer_Base::handlerForSigHUP(int signo)
#ifdef ENABLE_THREAD
# if defined(USE_LIBSSL) && !defined(OPENSSL_NO_OCSP) && defined(SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB)
if (pthread_ocsp) pthread_ocsp->resume();
if (pthread_ocsp) pthread_ocsp->resume();
# endif
if (u_pthread_time)
{
# ifdef DEBUG
(void) U_SYSCALL(gettimeofday, "%p,%p", u_now, 0);
((UTimeThread*)u_pthread_time)->before.set(*u_now);
# endif
((UTimeThread*)u_pthread_time)->watch_counter = 0;
((UTimeThread*)u_pthread_time)->resume();
}
if (u_pthread_time) ((UTimeThread*)u_pthread_time)->resume();
#endif
#ifdef U_LOG_ENABLE
@ -2174,7 +2124,7 @@ try_accept:
# ifdef U_LOG_ENABLE
if (isLog() &&
flag_loop && // NB: we check to avoid SIGTERM event...
CSOCKET->iState != -EINTR && // NB: we check to avoid log spurious EINTR on accept() by timer...
CSOCKET->iState != -EINTR && // NB: we check to avoid log spurious EINTR on accept() by any timer...
CSOCKET->iState != -EAGAIN)
{
CSOCKET->setMsgError();
@ -2772,18 +2722,6 @@ void UServer_Base::run()
if (preforked_num_kids <= 0) pid_to_wait = pid;
if (set_realtime_priority) u_switch_to_realtime_priority(pid);
# ifdef ENABLE_THREAD
if (u_pthread_time)
{
# ifdef DEBUG
(void) U_SYSCALL(gettimeofday, "%p,%p", u_now, 0);
((UTimeThread*)u_pthread_time)->before.set(*u_now);
# endif
((UTimeThread*)u_pthread_time)->watch_counter = 0;
}
# endif
}
if (proc->child())
@ -3069,7 +3007,6 @@ const char* UServer_Base::dump(bool reset) const
<< "last_event " << last_event << '\n'
<< "verify_mode " << verify_mode << '\n'
<< "shared_data_add " << shared_data_add << '\n'
<< "ptr_static_date " << (void*)ptr_static_date << '\n'
<< "ptr_shared_data " << (void*)ptr_shared_data << '\n'
<< "preforked_num_kids " << preforked_num_kids << '\n'
<< "log (ULog " << (void*)log << ")\n"

View File

@ -712,7 +712,7 @@ uint32_t UOptions::getopt(int argc, char** argv, int* poptind)
"SSL support..........:%W " LIBSSL_ENABLE "%W\n"
"SSH support..........:%W " LIBSSH_ENABLE "%W\n"
"LDAP support.........:%W " LIBLDAP_ENABLE "%W\n"
"LDAP support.........:%W " LIBLDAP_ENABLE "%W\n"
"cURL support.........:%W " LIBCURL_ENABLE "%W\n"
"XML support..........:%W " LIBEXPAT_ENABLE "%W\n"
"MAGIC support........:%W " MAGIC_ENABLE "%W\n"
"SQLite support.......:%W " SQLITE_ENABLE "%W\n"

View File

@ -19,7 +19,7 @@
# include <sys/syscall.h>
#endif
typedef void* (*exec_t)(void*);
typedef void* (*exec_t) (void*);
typedef void (*cleanup_t)(void*);
#ifndef HAVE_NANOSLEEP
@ -138,15 +138,9 @@ void UThread::stop()
(void) U_SYSCALL(pthread_cancel, "%p", priv->_tid);
if (bdetached == false)
{
(void) U_SYSCALL(pthread_join, "%p,%p", priv->_tid, 0);
}
if (bdetached == false) (void) U_SYSCALL(pthread_join, "%p,%p", priv->_tid, 0);
#ifdef HAVE_PTHREAD_YIELD
else
{
(void) U_SYSCALL_NO_PARAM(pthread_yield);
}
else (void) U_SYSCALL_NO_PARAM(pthread_yield);
#endif
}
@ -179,13 +173,6 @@ void UThread::close()
}
}
void UThread::threadCleanup(UThread* th)
{
U_TRACE(0, "UThread::threadCleanup(%p)", th)
th->close();
}
void UThread::yield()
{
U_TRACE(1, "UThread::yield()")
@ -202,17 +189,17 @@ void UThread::yield()
if (bcancel)
{
# ifdef sigemptyset
# ifdef sigemptyset
sigemptyset(&cancel);
# else
# else
(void) U_SYSCALL(sigemptyset, "%p", &cancel);
# endif
# endif
# ifdef sigaddset
# ifdef sigaddset
sigaddset(&cancel, CCXX_SIG_THREAD_CANCEL);
# else
# else
(void) U_SYSCALL(sigaddset, "%p,%d", &cancel, CCXX_SIG_THREAD_CANCEL);
# endif
# endif
(void) U_SYSCALL(pthread_sigmask, "%d,%p,%p", SIG_UNBLOCK, &cancel, &old);
}
@ -254,11 +241,11 @@ void UThread::sigInstall(int signo)
struct sigaction sa;
# ifdef sigemptyset
#ifdef sigemptyset
sigemptyset(&sa.sa_mask);
# else
#else
(void) U_SYSCALL(sigemptyset, "%p", &sa.sa_mask);
# endif
#endif
#ifdef SA_RESTART
sa.sa_flags = SA_RESTART;
@ -364,25 +351,25 @@ void UThread::execHandler(UThread* th)
sigset_t mask;
# ifdef sigemptyset
#ifdef sigemptyset
sigemptyset(&mask);
# else
#else
(void) U_SYSCALL(sigemptyset, "%p", &mask);
# endif
#endif
# ifdef sigaddset
#ifdef sigaddset
// sigaddset(&mask, SIGHUP);
sigaddset(&mask, SIGINT);
sigaddset(&mask, SIGABRT);
sigaddset(&mask, SIGPIPE);
sigaddset(&mask, SIGALRM);
# else
#else
// (void) U_SYSCALL(sigaddset, "%p,%d", &mask, SIGHUP);
(void) U_SYSCALL(sigaddset, "%p,%d", &mask, SIGINT);
(void) U_SYSCALL(sigaddset, "%p,%d", &mask, SIGABRT);
(void) U_SYSCALL(sigaddset, "%p,%d", &mask, SIGPIPE);
(void) U_SYSCALL(sigaddset, "%p,%d", &mask, SIGALRM);
# endif
#endif
(void) U_SYSCALL(pthread_sigmask, "%d,%p,%p", SIG_BLOCK, &mask, 0);
@ -394,19 +381,19 @@ void UThread::execHandler(UThread* th)
// of Linux threads, it was possible to stop a single thread with SIGSTOP, but this behaviour has now been fixed
// to conform to the Posix standard (so it stops all threads in the process)
# ifdef sigemptyset
# ifdef sigemptyset
sigemptyset(&mask);
# else
# else
(void) U_SYSCALL(sigemptyset, "%p", &mask);
# endif
# endif
# ifdef sigaddset
# ifdef sigaddset
sigaddset(&mask, U_SIGSTOP);
sigaddset(&mask, U_SIGCONT);
# else
# else
(void) U_SYSCALL(sigaddset, "%p,%d", &mask, U_SIGSTOP);
(void) U_SYSCALL(sigaddset, "%p,%d", &mask, U_SIGCONT);
# endif
# endif
(void) U_SYSCALL(pthread_sigmask, "%d,%p,%p", SIG_UNBLOCK, &mask, 0);
@ -575,10 +562,10 @@ bool UThread::initIPC(pthread_mutex_t* mutex, pthread_cond_t* cond)
{
pthread_mutexattr_t mutexattr;
if (U_SYSCALL(pthread_mutexattr_init, "%p", &mutexattr) == -1 ||
U_SYSCALL(pthread_mutexattr_setrobust, "%p,%d", &mutexattr, PTHREAD_MUTEX_ROBUST) == -1 ||
U_SYSCALL(pthread_mutexattr_setpshared, "%p,%d", &mutexattr, PTHREAD_PROCESS_SHARED) == -1 ||
U_SYSCALL(pthread_mutex_init, "%p,%p", mutex, &mutexattr) == -1)
if (U_SYSCALL(pthread_mutexattr_init, "%p", &mutexattr) != 0 ||
U_SYSCALL(pthread_mutexattr_setrobust, "%p,%d", &mutexattr, PTHREAD_MUTEX_ROBUST) != 0 ||
U_SYSCALL(pthread_mutexattr_setpshared, "%p,%d", &mutexattr, PTHREAD_PROCESS_SHARED) != 0 ||
U_SYSCALL(pthread_mutex_init, "%p,%p", mutex, &mutexattr) != 0)
{
U_RETURN(false);
}
@ -588,9 +575,9 @@ bool UThread::initIPC(pthread_mutex_t* mutex, pthread_cond_t* cond)
{
pthread_condattr_t condattr;
if (U_SYSCALL(pthread_condattr_init, "%p", &condattr) == -1 ||
U_SYSCALL(pthread_condattr_setpshared, "%p,%d", &condattr, PTHREAD_PROCESS_SHARED) == -1 ||
U_SYSCALL(pthread_cond_init, "%p,%p", cond, &condattr) == -1)
if (U_SYSCALL(pthread_condattr_init, "%p", &condattr) != 0 ||
U_SYSCALL(pthread_condattr_setpshared, "%p,%d", &condattr, PTHREAD_PROCESS_SHARED) != 0 ||
U_SYSCALL(pthread_cond_init, "%p,%p", cond, &condattr) != 0)
{
U_RETURN(false);
}

View File

@ -127,8 +127,14 @@ long UTimeVal::restart()
{
U_TRACE(1, "UTimeVal::restart()")
#ifdef DEBUG
long tv_sec_old = u_now->tv_sec;
#endif
(void) U_SYSCALL(gettimeofday, "%p,%p", u_now, 0);
U_INTERNAL_ASSERT(tv_sec_old <= u_now->tv_sec)
struct timeval time_from_last_start = { u_now->tv_sec - tv_sec, u_now->tv_usec - tv_usec };
tv_sec = u_now->tv_sec;
@ -151,8 +157,14 @@ long UTimeVal::stop()
{
U_TRACE(1, "UTimeVal::stop()")
#ifdef DEBUG
long tv_sec_old = u_now->tv_sec;
#endif
(void) U_SYSCALL(gettimeofday, "%p,%p", u_now, 0);
U_INTERNAL_ASSERT(tv_sec_old <= u_now->tv_sec)
struct timeval time_elapsed = { u_now->tv_sec - tv_sec, u_now->tv_usec - tv_usec };
if (time_elapsed.tv_usec < 0L)

File diff suppressed because it is too large Load Diff

View File

@ -55,22 +55,22 @@ void USemaphore::init(sem_t* ptr, int resource)
U_INTERNAL_ASSERT_DIFFERS(first, next)
}
# ifdef DEBUG
# ifdef DEBUG
int _value = getValue();
if (_value != resource) U_ERROR("USemaphore::init(%p,%u) failed - value = %d", ptr, resource, _value);
# endif
# endif
#else
# ifdef _MSWINDOWS_
# ifdef _MSWINDOWS_
psem = (sem_t*) ::CreateSemaphore((LPSECURITY_ATTRIBUTES)NULL, (LONG)resource, 1000000, (LPCTSTR)NULL);
# else
# else
if (flock == 0)
{
flock = U_NEW(UFile);
if (flock->mkTemp(0) == false) U_ERROR("USemaphore::init(%p,%u) failed", ptr, resource);
}
# endif
# endif
#endif
}
@ -88,11 +88,11 @@ USemaphore::~USemaphore()
(void) sem_destroy(psem); // Free resources associated with semaphore object sem
#else
# ifdef _MSWINDOWS_
# ifdef _MSWINDOWS_
::CloseHandle((HANDLE)psem);
# else
# else
(void) flock->close();
# endif
# endif
#endif
}
@ -116,11 +116,11 @@ void USemaphore::post()
U_INTERNAL_DUMP("value = %d", getValue())
#else
# ifdef _MSWINDOWS_
# ifdef _MSWINDOWS_
::ReleaseSemaphore((HANDLE)psem, 1, (LPLONG)NULL);
# else
# else
(void) flock->unlock();
# endif
# endif
#endif
}
@ -190,11 +190,11 @@ bool USemaphore::wait(time_t timeoutMS)
if (rc == 0) U_RETURN(true);
#else
# ifdef _MSWINDOWS_
# ifdef _MSWINDOWS_
if (::WaitForSingleObject((HANDLE)psem, timeoutMS) == WAIT_OBJECT_0) U_RETURN(true);
# else
# else
if (flock->unlock()) U_RETURN(true);
# endif
# endif
#endif
U_RETURN(false);
@ -234,11 +234,11 @@ wait:
U_INTERNAL_ASSERT_EQUALS(rc, 0)
#else
# ifdef _MSWINDOWS_
# ifdef _MSWINDOWS_
(void) ::WaitForSingleObject((HANDLE)psem, INFINITE);
# else
# else
(void) flock->unlock();
# endif
# endif
#endif
}

View File

@ -19,6 +19,10 @@
#include <ulib/utility/services.h>
#include <ulib/net/server/server.h>
#ifdef USE_LIBUUID
# include <uuid/uuid.h>
#endif
unsigned char UServices::key[16];
/* coverity[+alloc] */
@ -222,13 +226,15 @@ int UServices::askToLDAP(UString* pinput, UHashMap<UString>* ptable, const char*
U_RETURN(0);
}
// creat a new unique UUID value - 8 bytes (64 bits) long
uint64_t UServices::getUniqUID()
{
U_TRACE(0, "UServices::getUniqUID()")
static uint64_t unique_num;
if (unique_num == 0) unique_num = (uint64_t)u_now->tv_usec;
if (unique_num == 0) unique_num = (uint64_t)u_seed_hash;
uint64_t _uid = (((uint64_t)u_pid) << 56) |
((((uint64_t)u_now->tv_sec) & (0xfffffULL << 20)) << 16) |
@ -237,27 +243,75 @@ uint64_t UServices::getUniqUID()
U_RETURN(_uid);
}
#ifdef USE_LIBUUID
// creat a new unique UUID value - 16 bytes (128 bits) long
// return from the binary representation a 36-byte string (plus tailing '\0') of the form 1b4e28ba-2fa1-11d2-883f-0016d3cca427
uuid_t UServices::uuid; // typedef unsigned char uuid_t[16];
UString UServices::getUUID()
{
U_TRACE(1, "UServices::getUUID()")
UString id(37U);
UString buffer(36U);
char* id = buffer.data();
U_SYSCALL_VOID(uuid_generate, "%p", uuid);
U_SYSCALL_VOID(uuid_unparse, "%p", uuid, id.data());
#ifdef USE_LIBUUID
uuid_t uuid; // typedef unsigned char uuid_t[16];
id.size_adjust(36U);
U_SYSCALL_VOID(uuid_generate, "%p", uuid);
U_SYSCALL_VOID(uuid_unparse, "%p,%p", uuid, id);
#else
static unsigned short clock_seq;
U_RETURN_STRING(id);
}
unsigned short clock_seq_low = ++clock_seq & 0xff;
unsigned short clock_seq_hi_variant = (clock_seq >> 8) & 0x3f;
uint64_t node = getUniqUID(),
ossp_time = (((uint64_t)u_now->tv_sec + (141427ULL * 24ULL * 60ULL * 60ULL)) * 10000000ULL) + (u_now->tv_usec > 0 ? u_now->tv_usec * 10 : 0);
uint32_t time_low = htonl( ossp_time & 0xffffffff),
time_mid = htons((ossp_time >> 32) & 0x0000ffff),
time_hi_and_version = htons((ossp_time >> 48) & 0x00000fff);
#define U_APPEND_HEX(value, offset) \
*id++ = u_hex_upper[(((char*)&value)[offset] >> 4) & 0x0F]; \
*id++ = u_hex_upper[(((char*)&value)[offset] ) & 0x0F];
U_APPEND_HEX(time_low, 0);
U_APPEND_HEX(time_low, 1);
U_APPEND_HEX(time_low, 2);
U_APPEND_HEX(time_low, 3);
*id++ = '-';
U_APPEND_HEX(time_mid, 0);
U_APPEND_HEX(time_mid, 1);
*id++ = '-';
U_APPEND_HEX(time_hi_and_version, 0);
U_APPEND_HEX(time_hi_and_version, 1);
*id++ = '-';
U_APPEND_HEX(clock_seq_hi_variant, 0);
U_APPEND_HEX(clock_seq_low, 0);
*id++ = '-';
U_APPEND_HEX(node, 0);
U_APPEND_HEX(node, 1);
U_APPEND_HEX(node, 2);
U_APPEND_HEX(node, 3);
U_APPEND_HEX(node, 4);
U_APPEND_HEX(node, 5);
#undef U_APPEND_HEX(value, offset)
#endif
buffer.size_adjust(36U);
U_RETURN_STRING(buffer);
}
#ifdef USE_LIBSSL
# include <openssl/err.h>
# include <openssl/engine.h>

View File

@ -956,7 +956,7 @@ void UHTTP::ctor()
/**
* Set up static environment variables
* -------------------------------------------------------------------------------------------------------------------------------------------
* server static variable Description
* server static variable Description
* -------------------------------------------------------------------------------------------------------------------------------------------
* SERVER_PORT
* SERVER_ADDR
@ -966,14 +966,14 @@ void UHTTP::ctor()
* GATEWAY_INTERFACE CGI specification revision with which this server complies. Format: CGI/revision
* -------------------------------------------------------------------------------------------------------------------------------------------
* Example:
* ----------------------------------------------------------------------------------------------------------------------------
* -------------------------------------------------------------------------------------------------------------------------------------------
* SERVER_PORT=80
* SERVER_ADDR=127.0.0.1
* SERVER_NAME=localhost
* DOCUMENT_ROOT="/var/www/localhost/htdocs"
* SERVER_SOFTWARE=Apache
* GATEWAY_INTERFACE=CGI/1.1
* ----------------------------------------------------------------------------------------------------------------------------
* -------------------------------------------------------------------------------------------------------------------------------------------
*/
U_INTERNAL_ASSERT_POINTER(UServer_Base::cenvironment)
@ -1047,14 +1047,14 @@ next:
cache_file = U_NEW(UHashMap<UHTTP::UFileCacheData*>);
#ifdef U_STATIC_ONLY
# if defined(U_ALIAS) && !defined(U_STATIC_SERVLET_WI_AUTH)
# if defined(U_ALIAS) && !defined(U_STATIC_SERVLET_WI_AUTH)
U_INTERNAL_ASSERT_EQUALS(virtual_host, false)
# endif
# endif
/**
* I do know that to include code in the middle of a function is hacky and dirty, but this is the best solution that I could figure out.
* If you have some idea to clean it up, please, don't hesitate and let me know
*/
# include "../net/server/plugin/usp/loader.autoconf.cpp"
# include "../net/server/plugin/usp/loader.autoconf.cpp"
#endif
U_INTERNAL_ASSERT_EQUALS(file_not_in_cache_data, 0)
@ -1101,7 +1101,7 @@ next:
# ifdef U_STDCPP_ENABLE
if (content_cache)
{
n += (content_cache.size() / (1024 + 512)); // NB: we assume as medium file size ~1.5k...
n += (content_cache.size() / (1024 + 512)); // NB: we assume as medium file size something like ~1.5k...
UString2Object(U_STRING_TO_PARAM(content_cache), *cache_file);
@ -1492,7 +1492,15 @@ __pure bool UHTTP::isMobile()
}
/**
* ---------------------------------------------------------------------------------------------------------------------------
* HTTP message
* ---------------------------------------------------------------------------------------------------------------------------
* There are four parts to an HTTP request:
* ---------------------------------------------------------------------------------------------------------------------------
* 1) the request line [REQUIRED]: the method, the URL, the version of the protocol
* 2) the request headers [OPTIONAL]: a series of lines (one per) in the format of name, colon(:), and the value of the header
* 3) a blank line [REQUIRED]: worth mentioning by itself
* 4) the request Body [OPTIONAL]: used in POST/PUT/PATCH requests to send content to the server
* ======================================================================================
* Read the request line and attached headers. A typical http request will take the form:
* ======================================================================================
@ -1641,14 +1649,18 @@ int UHTTP::handlerDataPending()
U_RETURN(-1);
}
// TODO: HTTP/2 implementation
U_ClientImage_data_missing = false;
UClientImage_Base::setRequestNeedProcessing();
(void) manageRequest();
/*
return 1 // child of parallelization
return -1 // parent of parallelization
*/
U_RETURN(-1);
U_RETURN(0);
}
else
#endif
@ -1661,22 +1673,26 @@ bool UHTTP::scanfHeaderRequest(const char* ptr, uint32_t size)
U_TRACE(0, "UHTTP::scanfHeaderRequest(%.*S,%u)", size, ptr, size)
/**
* ------------------------------------------------------------------
* Check HTTP request.
* -------------------------------------------------------------------
* Check HTTP request
* -------------------------------------------------------------------
* The default is GET for input requests and POST for output requests.
* Other possible alternatives are:
* ------------------------------------------------------------------
* -------------------------------------------------------------------
* - PUT
* - HEAD
* - COPY
* - PATCH
* - DELETE
* - OPTIONS
* ---------------------- NOT implemented ---------------------------
* ---------------------- NOT implemented ----------------------------
* - CONNECT
* - TRACE (because can send client cookie information, dangerous...)
* ------------------------------------------------------------------
* See http://ietf.org/rfc/rfc2616.txt for further information about HTTP request methods
* -------------------------------------------------------------------
* for further information about HTTP request methods see:
*
* http://ietf.org/rfc/rfc2616.txt
* -------------------------------------------------------------------
*/
unsigned char c;
@ -3169,17 +3185,6 @@ bool UHTTP::callService(const UString& path) // NB: it is used also by server_pl
U_RETURN(true);
}
/**
* ---------------------------------------------------------------------------------------------------------------------------
* There are four parts to an HTTP request:
* ---------------------------------------------------------------------------------------------------------------------------
* 1) the request line [REQUIRED]: the method, the URL, the version of the protocol
* 2) the request headers [OPTIONAL]: a series of lines (one per) in the format of name, colon(:), and the value of the header
* 3) a blank line [REQUIRED]: worth mentioning by itself
* 4) the request Body [OPTIONAL]: used in POST/PUT/PATCH requests to send content to the server
* ---------------------------------------------------------------------------------------------------------------------------
*/
bool UHTTP::handlerCache()
{
U_TRACE(0, "UHTTP::handlerCache()")
@ -3338,7 +3343,6 @@ int UHTTP::handlerREAD()
U_INTERNAL_ASSERT(*UClientImage_Base::request)
const char* ptr;
bool result_read_body;
// ------------------------------
@ -3452,8 +3456,7 @@ dmiss: UClientImage_Base::setRequestProcessed();
U_INTERNAL_ASSERT_EQUALS(U_ClientImage_data_missing, false)
if (result_read_body) UClientImage_Base::size_request += U_http_info.clength;
else
if (result_read_body == false)
{
U_INTERNAL_DUMP("UServer_Base::csocket->isClosed() = %b UClientImage_Base::wbuffer(%u) = %V",
UServer_Base::csocket->isClosed(), UClientImage_Base::wbuffer->size(), UClientImage_Base::wbuffer->rep)
@ -3464,11 +3467,22 @@ dmiss: UClientImage_Base::setRequestProcessed();
U_RETURN(U_PLUGIN_HANDLER_FINISHED);
}
UClientImage_Base::size_request += U_http_info.clength;
}
#endif
return manageRequest();
}
int UHTTP::manageRequest()
{
U_TRACE(0, "UHTTP::manageRequest()")
// check the HTTP message
U_INTERNAL_DUMP("U_ClientImage_request = %d %B", U_ClientImage_request, U_ClientImage_request)
U_ASSERT(UClientImage_Base::isRequestNotFound())
// manage alias uri
@ -3501,6 +3515,7 @@ dmiss: UClientImage_Base::setRequestProcessed();
if (valias)
{
UString str;
const char* ptr;
int i, n = valias->size();
// Ex: /admin /admin.html
@ -3512,7 +3527,6 @@ dmiss: UClientImage_Base::setRequestProcessed();
int flag = 0;
str = (*valias)[i];
ptr = str.data();
int len = str.size();
@ -3624,7 +3638,7 @@ set_uri: U_http_info.uri = alias->data();
// we check if it is present as shared file (without the virtual host prefix)
// ------------------------------------------------------------------------------
# ifndef U_SERVER_CAPTIVE_PORTAL
ptr = pathname->c_pointer(u_cwd_len);
const char* ptr = pathname->c_pointer(u_cwd_len);
# ifdef U_ALIAS
U_INTERNAL_DUMP("virtual_host = %b U_http_host_vlen = %u U_http_is_request_nostat = %b", virtual_host, U_http_host_vlen, U_http_is_request_nostat)
@ -4224,9 +4238,9 @@ void UHTTP::setEndRequestProcessing()
}
# endif
U_INTERNAL_ASSERT_EQUALS(U_HTTP_DATE2, iov_vec[2].iov_base)
U_INTERNAL_ASSERT_EQUALS(iov_vec[2].iov_base, ULog::date.date2)
ULog::updateStaticDate(U_HTTP_DATE2, 2);
ULog::updateDate2();
UServer_Base::apache_like_log->write(iov_vec, 10);
@ -5199,11 +5213,11 @@ uint32_t UHTTP::processForm()
{
U_ASSERT(isPOST())
// ------------------------------------------------------------------------
// -------------------------------------------------------------------------
// POST
// ------------------------------------------------------------------------
// -------------------------------------------------------------------------
// Content-Type: application/x-www-form-urlencoded OR multipart/form-data...
// ------------------------------------------------------------------------
// -------------------------------------------------------------------------
if (U_HTTP_CTYPE_MEMEQ("application/x-www-form-urlencoded")) tmp = *UClientImage_Base::body;
else
@ -5438,6 +5452,13 @@ UString UHTTP::getHeaderForResponse()
UClientImage_Base::setRequestProcessed();
#ifndef U_HTTP2_DISABLE
if (U_http_version == '2')
{
return UString::getStringNull();
}
#endif
UClientImage_Base::setHeaderForResponse(6+29+2+12+2); // Date: Wed, 20 Jun 2012 11:43:17 GMT\r\nServer: ULib\r\n
if (U_http_info.nResponseCode == HTTP_NOT_IMPLEMENTED ||
@ -5665,7 +5686,8 @@ void UHTTP::setResponse(const UString* content_type, UString* pbody)
"<address>ULib Server</address>\r\n" \
"</body></html>\r\n"
/*------------------------------------------------------------------------------------------------------------------
/**
* ------------------------------------------------------------------------------------------------------------------
* http://sebastians-pamphlets.com/the-anatomy-of-http-redirects-301-302-307/
* ------------------------------------------------------------------------------------------------------------------
* HTTP/1.0
@ -5695,6 +5717,7 @@ void UHTTP::setResponse(const UString* content_type, UString* pbody)
* the request method was HEAD, the entity of the response SHOULD contain a short hypertext note with a hyperlink to the new
* URI(s), since many pre-HTTP/1.1 user agents do not understand the 307 status. Therefore, the note SHOULD contain the
* information necessary for a user to repeat the original request on the new URI.
* ------------------------------------------------------------------------------------------------------------------
*/
void UHTTP::setRedirectResponse(int mode, const char* ptr_location, uint32_t len_location)
@ -9598,12 +9621,12 @@ void UHTTP::initApacheLikeLog()
iov_vec[1].iov_base = (caddr_t) " - - [";
iov_vec[1].iov_len = U_CONSTANT_SIZE(" - - [");
iov_vec[2].iov_base = (caddr_t) U_HTTP_DATE2; // %d/%b/%Y:%T %z - 21/May/2012:16:29:41 +0200
iov_vec[2].iov_base = (caddr_t)ULog::date.date2; // %d/%b/%Y:%T %z - 21/May/2012:16:29:41 +0200
iov_vec[2].iov_len = 26;
iov_vec[3].iov_base = (caddr_t) "] \"";
iov_vec[3].iov_len = U_CONSTANT_SIZE("] \"");
// request
iov_vec[5].iov_base = (caddr_t) iov_buffer; // response_code, body_len
iov_vec[5].iov_base = (caddr_t)iov_buffer; // response_code, body_len
// referer
iov_vec[7].iov_base = (caddr_t) "\" \"";
iov_vec[7].iov_len = U_CONSTANT_SIZE("\" \"");

View File

@ -22,9 +22,9 @@ export ORM_DRIVER ORM_OPTION UMEMPOOL
# ----------------------------------------------------------------------------------------------------------------------------------------------------------
# PLAINTEXT
# ----------------------------------------------------------------------------------------------------------------------------------------------------------
UMEMPOOL="982,0,0,36,9846,-24,-23,1727,1151"
sed -i "s|TCP_LINGER_SET .*|TCP_LINGER_SET 0|g" benchmark/FrameworkBenchmarks/fbenchmark.cfg
sed -i "s|LISTEN_BACKLOG .*|LISTEN_BACKLOG 16384|g" benchmark/FrameworkBenchmarks/fbenchmark.cfg
#UMEMPOOL="982,0,0,36,9846,-24,-23,1727,1151"
#sed -i "s|TCP_LINGER_SET .*|TCP_LINGER_SET 0|g" benchmark/FrameworkBenchmarks/fbenchmark.cfg
#sed -i "s|LISTEN_BACKLOG .*|LISTEN_BACKLOG 16384|g" benchmark/FrameworkBenchmarks/fbenchmark.cfg
#sed -i "s|CLIENT_THRESHOLD .*|CLIENT_THRESHOLD 4000|g" benchmark/FrameworkBenchmarks/fbenchmark.cfg
#sed -i "s|CLIENT_FOR_PARALLELIZATION .*|CLIENT_FOR_PARALLELIZATION 8000|g" benchmark/FrameworkBenchmarks/fbenchmark.cfg
# ----------------------------------------------------------------------------------------------------------------------------------------------------------
@ -58,9 +58,9 @@ export ORM_DRIVER ORM_OPTION UMEMPOOL
# ----------------------------------------------------------------------------------------------------------------------------------------------------------
# JSON
# ----------------------------------------------------------------------------------------------------------------------------------------------------------
#UMEMPOOL="56,0,0,40,150,-24,-13,-20,0"
#sed -i "s|TCP_LINGER_SET .*|TCP_LINGER_SET 0|g" benchmark/FrameworkBenchmarks/fbenchmark.cfg
#sed -i "s|LISTEN_BACKLOG .*|LISTEN_BACKLOG 256|g" benchmark/FrameworkBenchmarks/fbenchmark.cfg
UMEMPOOL="56,0,0,40,150,-24,-13,-20,0"
sed -i "s|TCP_LINGER_SET .*|TCP_LINGER_SET 0|g" benchmark/FrameworkBenchmarks/fbenchmark.cfg
sed -i "s|LISTEN_BACKLOG .*|LISTEN_BACKLOG 256|g" benchmark/FrameworkBenchmarks/fbenchmark.cfg
#sed -i "s|CLIENT_THRESHOLD .*|CLIENT_THRESHOLD 50|g" benchmark/FrameworkBenchmarks/fbenchmark.cfg
#sed -i "s|CLIENT_FOR_PARALLELIZATION .*|CLIENT_FOR_PARALLELIZATION 100|g" benchmark/FrameworkBenchmarks/fbenchmark.cfg
# ----------------------------------------------------------------------------------------------------------------------------------------------------------

View File

@ -3,7 +3,7 @@ userver {
PORT 8080
PREFORK_CHILD 4
TCP_LINGER_SET 0
LISTEN_BACKLOG 16384
LISTEN_BACKLOG 256
DOCUMENT_ROOT benchmark/FrameworkBenchmarks/ULib/www
PID_FILE benchmark/FrameworkBenchmarks/ULib/userver_tcp.pid

View File

@ -16,10 +16,11 @@ rm -f $DOC_ROOT/web_server_multiclient.log* \
trace.*userver_*.[0-9]* object.*userver_*.[0-9]* stack.*userver_*.[0-9]* mempool.*userver_*.[0-9]* \
$DOC_ROOT/trace.*userver_*.[0-9]* $DOC_ROOT/object.*userver_*.[0-9]* $DOC_ROOT/stack.*userver_*.[0-9]* $DOC_ROOT/mempool.*userver_*.[0-9]*
#UTRACE="0 100M 0"
#UTRACE="5 100M 0"
#UTRACE_SIGNAL="0 100M -1"
#UOBJDUMP="0 10M 100"
#USIMERR="error.sim"
export UTRACE UOBJDUMP USIMERR
export UTRACE UOBJDUMP USIMERR UTRACE_SIGNAL
if [ "$TERM" = "msys" ]; then
export TMPDIR="c:/tmp"

View File

@ -39,11 +39,8 @@ U_EXPORT main (int argc, char* argv[])
// U_ASSERT( result1 == U_STRING_FROM_CONSTANT("test_services.cpp\n") )
#ifdef USE_LIBUUID
buffer = UServices::getUUID();
U_INTERNAL_DUMP("buffer = %#.*S", U_STRING_TO_TRACE(buffer))
U_INTERNAL_DUMP("UServices::uuid = %#.*S", 16, UServices::uuid)
#endif
cmd = U_STRING_FROM_CONSTANT("cat test_services.cpp");
result2 = UCommand::outputCommand(cmd, 0, -1, fd_stderr);

View File

@ -53,39 +53,35 @@ U_EXPORT main (int argc, char* argv[])
U_ASSERT( UTimeDate::getSecondFromTime("19030314104248Z", true, "%4u%2u%2u%2u%2u%2uZ") < u_now->tv_sec )
/*
typedef struct static_date {
struct timeval _timeval; // => u_now
char lock1[1];
typedef struct log_date {
char date1[17+1]; // 18/06/12 18:45:56
char lock2[1];
char date2[26+1]; // 04/Jun/2012:18:18:37 +0200
char lock3[1];
char date3[6+29+2+12+2+19+1]; // Date: Wed, 20 Jun 2012 11:43:17 GMT\r\nServer: ULib\r\nConnection: close\r\n
} static_date;
} log_date;
*/
ULog::static_date log_data;
ULog::log_date log_date;
(void) u_strftime2(log_data.date1, 17, "%d/%m/%y %T", u_now->tv_sec + u_now_adjust);
(void) u_strftime2(log_data.date2, 26, "%d/%b/%Y:%T %z", u_now->tv_sec + u_now_adjust);
(void) u_strftime2(log_data.date3, 6+29+2+12+2+17+2, "Date: %a, %d %b %Y %T GMT\r\nServer: ULib\r\nConnection: close\r\n", u_now->tv_sec);
(void) u_strftime2(log_date.date1, 17, "%d/%m/%y %T", u_now->tv_sec + u_now_adjust);
(void) u_strftime2(log_date.date2, 26, "%d/%b/%Y:%T %z", u_now->tv_sec + u_now_adjust);
(void) u_strftime2(log_date.date3, 6+29+2+12+2+17+2, "Date: %a, %d %b %Y %T GMT\r\nServer: ULib\r\nConnection: close\r\n", u_now->tv_sec);
U_INTERNAL_DUMP("date1 = %.17S date2 = %.26S date3+6 = %.29S", log_data.date1, log_data.date2, log_data.date3+6)
U_INTERNAL_DUMP("date1 = %.17S date2 = %.26S date3+6 = %.29S", log_date.date1, log_date.date2, log_date.date3+6)
/*
for (int i = 0; i < 360; ++i)
{
u_now->tv_sec++;
UTimeDate::updateTime(log_data.date1 + 12);
UTimeDate::updateTime(log_data.date2 + 15);
UTimeDate::updateTime(log_data.date3+6 + 20);
UTimeDate::updateTime(log_date.date1 + 12);
UTimeDate::updateTime(log_date.date2 + 15);
UTimeDate::updateTime(log_date.date3+6 + 20);
cout.write(log_data.date1, 17);
cout.write(log_date.date1, 17);
cout.write(" - ", 3);
cout.write(log_data.date2, 26);
cout.write(log_date.date2, 26);
cout.write(" - ", 3);
cout.write(log_data.date3+6, 29);
cout.write(log_date.date3+6, 29);
cout.put('\n');
}
*/

View File

@ -39,11 +39,8 @@ U_EXPORT main (int argc, char* argv[])
// U_ASSERT( result1 == U_STRING_FROM_CONSTANT("test_services.cpp\n") )
#ifdef USE_LIBUUID
buffer = UServices::getUUID();
U_INTERNAL_DUMP("buffer = %#.*S", U_STRING_TO_TRACE(buffer))
U_INTERNAL_DUMP("UServices::uuid = %#.*S", 16, UServices::uuid)
#endif
cmd = U_STRING_FROM_CONSTANT("cat test_services.cpp");
result2 = UCommand::outputCommand(cmd, 0, -1, fd_stderr);