diff --git a/src/event/modules/ngx_devpoll_module.c b/src/event/modules/ngx_devpoll_module.c index 9bc743426..c8f368406 100644 --- a/src/event/modules/ngx_devpoll_module.c +++ b/src/event/modules/ngx_devpoll_module.c @@ -322,9 +322,10 @@ static int ngx_devpoll_set_event(ngx_event_t *ev, int event, u_int flags) int ngx_devpoll_process_events(ngx_log_t *log) { int events, n, i, j; - ngx_msec_t timer, delta; + ngx_msec_t timer; ngx_err_t err; ngx_cycle_t **cycle; + ngx_epoch_msec_t delta; ngx_connection_t *c; struct dvpoll dvp; struct timeval tv; @@ -332,7 +333,7 @@ int ngx_devpoll_process_events(ngx_log_t *log) timer = ngx_event_find_timer(); if (timer) { - gettimeofday(&tv, NULL); + ngx_gettimeofday(&tv); delta = tv.tv_sec * 1000 + tv.tv_usec / 1000; } else { @@ -366,7 +367,7 @@ int ngx_devpoll_process_events(ngx_log_t *log) nchanges = 0; - gettimeofday(&tv, NULL); + ngx_gettimeofday(&tv); if (ngx_cached_time != tv.tv_sec) { ngx_cached_time = tv.tv_sec; @@ -377,9 +378,9 @@ int ngx_devpoll_process_events(ngx_log_t *log) delta = tv.tv_sec * 1000 + tv.tv_usec / 1000 - delta; #if (NGX_DEBUG_EVENT) - ngx_log_debug(log, "devpoll timer: %d, delta: %d" _ timer _ delta); + ngx_log_debug(log, "devpoll timer: %d, delta: %d" _ timer _ (int)delta); #endif - ngx_event_expire_timers(delta); + ngx_event_expire_timers((ngx_msec_t) delta); } else { if (events == 0) { @@ -389,7 +390,7 @@ int ngx_devpoll_process_events(ngx_log_t *log) } #if (NGX_DEBUG_EVENT) - ngx_log_debug(log, "devpoll timer: %d, delta: %d" _ timer _ delta); + ngx_log_debug(log, "devpoll timer: %d, delta: %d" _ timer _ (int)delta); #endif } diff --git a/src/event/modules/ngx_iocp_module.c b/src/event/modules/ngx_iocp_module.c index 0a5ac5bd7..99a1eee4e 100644 --- a/src/event/modules/ngx_iocp_module.c +++ b/src/event/modules/ngx_iocp_module.c @@ -162,14 +162,16 @@ static int ngx_iocp_process_events(ngx_log_t *log) u_int key; size_t bytes; ngx_err_t err; - ngx_msec_t timer, delta; + ngx_msec_t timer; ngx_event_t *ev; + ngx_epoch_msec_t delta; ngx_event_ovlp_t *ovlp; timer = ngx_event_find_timer(); if (timer) { - delta = ngx_msec(); + ngx_gettimeofday(&tv); + delta = tv.tv_sec * 1000 + tv.tv_usec / 1000; } else { timer = INFINITE; @@ -189,11 +191,16 @@ static int ngx_iocp_process_events(ngx_log_t *log) err = 0; } - /* TODO: timer */ + ngx_gettimeofday(&tv); + + if (ngx_cached_time != tv.tv_sec) { + ngx_cached_time = tv.tv_sec; + ngx_time_update(); + } if (timer != INFINITE) { - delta = ngx_msec() - delta; - ngx_event_expire_timers(delta); + delta = tv.tv_sec * 1000 + tv.tv_usec / 1000 - delta; + ngx_event_expire_timers((ngx_msec_t) delta); } if (err) { diff --git a/src/event/modules/ngx_kqueue_module.c b/src/event/modules/ngx_kqueue_module.c index 831bc7720..d43fb0e15 100644 --- a/src/event/modules/ngx_kqueue_module.c +++ b/src/event/modules/ngx_kqueue_module.c @@ -311,12 +311,13 @@ static int ngx_kqueue_set_event(ngx_event_t *ev, int filter, u_int flags) static int ngx_kqueue_process_events(ngx_log_t *log) { - int events, instance, i; - ngx_err_t err; - ngx_msec_t timer, delta; - ngx_event_t *ev; - struct timeval tv; - struct timespec ts, *tp; + int events, instance, i; + ngx_err_t err; + ngx_msec_t timer; + ngx_event_t *ev; + ngx_epoch_msec_t delta; + struct timeval tv; + struct timespec ts, *tp; timer = ngx_event_find_timer(); @@ -324,11 +325,11 @@ static int ngx_kqueue_process_events(ngx_log_t *log) ts.tv_sec = timer / 1000; ts.tv_nsec = (timer % 1000) * 1000000; tp = &ts; - gettimeofday(&tv, NULL); + + ngx_gettimeofday(&tv); delta = tv.tv_sec * 1000 + tv.tv_usec / 1000; } else { - timer = 0; delta = 0; tp = NULL; } @@ -347,7 +348,7 @@ static int ngx_kqueue_process_events(ngx_log_t *log) nchanges = 0; - gettimeofday(&tv, NULL); + ngx_gettimeofday(&tv); if (ngx_cached_time != tv.tv_sec) { ngx_cached_time = tv.tv_sec; @@ -358,7 +359,7 @@ static int ngx_kqueue_process_events(ngx_log_t *log) delta = tv.tv_sec * 1000 + tv.tv_usec / 1000 - delta; #if (NGX_DEBUG_EVENT) - ngx_log_debug(log, "kevent timer: %d, delta: %d" _ timer _ delta); + ngx_log_debug(log, "kevent timer: %d, delta: %d" _ timer _ (int) delta); #endif /* @@ -366,7 +367,7 @@ static int ngx_kqueue_process_events(ngx_log_t *log) * because the new timers can be added during a processing */ - ngx_event_expire_timers(delta); + ngx_event_expire_timers((ngx_msec_t) delta); } else { if (events == 0) { @@ -376,7 +377,7 @@ static int ngx_kqueue_process_events(ngx_log_t *log) } #if (NGX_DEBUG_EVENT) - ngx_log_debug(log, "kevent timer: %d, delta: %d" _ timer _ delta); + ngx_log_debug(log, "kevent timer: %d, delta: %d" _ timer _ (int) delta); #endif } diff --git a/src/event/modules/ngx_poll_module.c b/src/event/modules/ngx_poll_module.c index 34f2b1191..e771e92fe 100644 --- a/src/event/modules/ngx_poll_module.c +++ b/src/event/modules/ngx_poll_module.c @@ -224,16 +224,19 @@ static int ngx_poll_process_events(ngx_log_t *log) { int ready, found, j; u_int nready, i; - ngx_msec_t timer, delta; + ngx_msec_t timer; ngx_err_t err; ngx_cycle_t **cycle; ngx_event_t *ev; + ngx_epoch_msec_t delta; ngx_connection_t *c; + struct timeval tv; timer = ngx_event_find_timer(); if (timer) { - delta = ngx_msec(); + ngx_gettimeofday(&tv); + delta = tv.tv_sec * 1000 + tv.tv_usec / 1000; } else { timer = INFTIM; @@ -259,15 +262,20 @@ static int ngx_poll_process_events(ngx_log_t *log) ngx_log_debug(log, "poll ready %d" _ ready); - /* TODO: time */ + ngx_gettimeofday(&tv); + + if (ngx_cached_time != tv.tv_sec) { + ngx_cached_time = tv.tv_sec; + ngx_time_update(); + } if ((int) timer != INFTIM) { - delta = ngx_msec() - delta; + delta = tv.tv_sec * 1000 + tv.tv_usec / 1000 - delta; #if (NGX_DEBUG_EVENT) - ngx_log_debug(log, "poll timer: %d, delta: %d" _ timer _ delta); + ngx_log_debug(log, "poll timer: %d, delta: %d" _ timer _ (int) delta); #endif - ngx_event_expire_timers(delta); + ngx_event_expire_timers((ngx_msec_t) delta); } else { if (ready == 0) { @@ -277,7 +285,7 @@ static int ngx_poll_process_events(ngx_log_t *log) } #if (NGX_DEBUG_EVENT) - ngx_log_debug(log, "poll timer: %d, delta: %d" _ timer _ delta); + ngx_log_debug(log, "poll timer: %d, delta: %d" _ timer _ (int) delta); #endif } diff --git a/src/event/modules/ngx_select_module.c b/src/event/modules/ngx_select_module.c index 082c0e335..1cde073a1 100644 --- a/src/event/modules/ngx_select_module.c +++ b/src/event/modules/ngx_select_module.c @@ -148,6 +148,7 @@ static int ngx_select_add_event(ngx_event_t *ev, int event, u_int flags) } #if (WIN32) + if ((event == NGX_READ_EVENT) && (max_read >= FD_SETSIZE) || (event == NGX_WRITE_EVENT) && (max_write >= FD_SETSIZE)) { @@ -165,7 +166,9 @@ static int ngx_select_add_event(ngx_event_t *ev, int event, u_int flags) FD_SET(c->fd, &master_write_fd_set); max_write++; } + #else + if (event == NGX_READ_EVENT) { FD_SET(c->fd, &master_read_fd_set); @@ -247,10 +250,14 @@ static int ngx_select_process_events(ngx_log_t *log) int ready, found; u_int i, nready; ngx_err_t err; - ngx_msec_t timer, delta; + ngx_msec_t timer; ngx_event_t *ev; ngx_connection_t *c; + ngx_epoch_msec_t delta; struct timeval tv, *tp; +#if (HAVE_SELECT_CHANGE_TIMEOUT) + static ngx_epoch_msec_t deltas = 0; +#endif work_read_fd_set = master_read_fd_set; work_write_fd_set = master_write_fd_set; @@ -264,7 +271,8 @@ static int ngx_select_process_events(ngx_log_t *log) #if (HAVE_SELECT_CHANGE_TIMEOUT) delta = 0; #else - delta = ngx_msec(); + ngx_gettimeofday(&tv); + delta = tv.tv_sec * 1000 + tv.tv_usec / 1000; #endif } else { @@ -314,32 +322,69 @@ static int ngx_select_process_events(ngx_log_t *log) ngx_log_debug(log, "select ready %d" _ ready); #endif - /* TODO: time */ +#if (HAVE_SELECT_CHANGE_TIMEOUT) if (timer) { -#if (HAVE_SELECT_CHANGE_TIMEOUT) delta = timer - (tv.tv_sec * 1000 + tv.tv_usec / 1000); -#if 0 /* - * update the cached time if the sum of the last deltas - * is more than 0.5 seconds + * learn the real time and update the cached time + * if the sum of the last deltas overcomes 1 second */ - deltas += delta; - if (deltas > 500000) { - ngx_cached_time = ngx_real_time(); - deltas = 0; - } -#endif -#else - delta = ngx_msec() - delta; -#endif + deltas += delta; + if (deltas > 1000) { + ngx_gettimeofday(&tv); + deltas = tv.tv_usec / 1000; + + if (ngx_cached_time != tv.tv_sec) { + ngx_cached_time = tv.tv_sec; + ngx_time_update(); + } + } #if (NGX_DEBUG_EVENT) - ngx_log_debug(log, "select timer: %d, delta: %d" _ timer _ delta); + ngx_log_debug(log, "select timer: %d, delta: %d" _ timer _ (int) delta); #endif - ngx_event_expire_timers(delta); + + ngx_event_expire_timers((ngx_msec_t) delta); + + } else { + ngx_gettimeofday(&tv); + + if (ngx_cached_time != tv.tv_sec) { + ngx_cached_time = tv.tv_sec; + ngx_time_update(); + } + + if (ready == 0) { + ngx_log_error(NGX_LOG_ALERT, log, 0, + "select() returned no events without timeout"); + return NGX_ERROR; + } + +#if (NGX_DEBUG_EVENT) + ngx_log_debug(log, "select timer: %d, delta: %d" _ timer _ (int) delta); +#endif + } + +#else /* HAVE_SELECT_CHANGE_TIMEOUT */ + + ngx_gettimeofday(&tv); + + if (ngx_cached_time != tv.tv_sec) { + ngx_cached_time = tv.tv_sec; + ngx_time_update(); + } + + if (timer) { + delta = tv.tv_sec * 1000 + tv.tv_usec / 1000 - delta; + +#if (NGX_DEBUG_EVENT) + ngx_log_debug(log, "select timer: %d, delta: %d" _ timer _ (int) delta); +#endif + + ngx_event_expire_timers((ngx_msec_t) delta); } else { if (ready == 0) { @@ -349,11 +394,12 @@ static int ngx_select_process_events(ngx_log_t *log) } #if (NGX_DEBUG_EVENT) - ngx_log_debug(log, "select timer: %d, delta: %d" _ timer _ delta); + ngx_log_debug(log, "select timer: %d, delta: %d" _ timer _ (int) delta); #endif - ngx_event_expire_timers(delta); } +#endif /* HAVE_SELECT_CHANGE_TIMEOUT */ + if (err) { ngx_log_error(NGX_LOG_ALERT, log, err, "select() failed"); return NGX_ERROR; diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c index 3a0ec8bfc..3f19b7833 100644 --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -429,7 +429,7 @@ int ngx_http_send_header(ngx_http_request_t *r) return NGX_OK; } - if (r->err_status) { + if (r->err_ctx) { r->headers_out.status = r->err_status; r->headers_out.status_line.len = 0; } @@ -499,17 +499,19 @@ int ngx_http_internal_redirect(ngx_http_request_t *r, } } - /* clear the modules contexts */ + if (r->err_ctx) { + + /* allocate the new modules contexts */ - if (r->error_page) { - r->err_status = r->headers_out.status; - r->err_ctx = r->ctx; r->ctx = ngx_pcalloc(r->pool, sizeof(void *) * ngx_http_max_module); if (r->ctx == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } } else { + + /* clear the modules contexts */ + ngx_memzero(r->ctx, sizeof(void *) * ngx_http_max_module); } diff --git a/src/http/ngx_http_parse_time.c b/src/http/ngx_http_parse_time.c index 09e56b4f0..26deb2841 100644 --- a/src/http/ngx_http_parse_time.c +++ b/src/http/ngx_http_parse_time.c @@ -232,16 +232,22 @@ time_t ngx_http_parse_time(char *value, size_t len) return NGX_ERROR; } - /* shift new year to 1st March, needed for Gauss's formula */ + /* shift new year to March 1, needed for Gauss's formula */ + if (--month <= 0) { month += 12; year -= 1; } - /* Gauss's formula for Grigorian days from 1 March 1 BC */ + + /* Gauss's formula for Grigorian days from 1 March 1 BC */ + return (365 * year + year / 4 - year / 100 + year / 400 + 367 * month / 12 + day - 31 - /* 719527 days are between 1 March 1 BC and 1 March 1970, - 31 and 28 days in Jan and Feb 1970 */ + /* + * 719527 days are between March 1, 1 BC and March 1, 1970, + * 31 and 28 days in January and February 1970 + */ + - 719527 + 31 + 28) * 86400 + hour * 3600 + min * 60 + sec; } diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h index a87c6dc4e..a91dbea57 100644 --- a/src/http/ngx_http_request.h +++ b/src/http/ngx_http_request.h @@ -205,8 +205,6 @@ struct ngx_http_request_s { unsigned bypass_cache:1; unsigned no_cache:1; - unsigned error_page:1; - #if 0 unsigned cachable:1; #endif diff --git a/src/http/ngx_http_special_response.c b/src/http/ngx_http_special_response.c index c1cb23aa4..8e93e90ce 100644 --- a/src/http/ngx_http_special_response.c +++ b/src/http/ngx_http_special_response.c @@ -203,11 +203,12 @@ int ngx_http_special_response_handler(ngx_http_request_t *r, int error) clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); - if (!r->error_page && clcf->error_pages) { + if (r->err_ctx == NULL && clcf->error_pages) { err_page = clcf->error_pages->elts; for (i = 0; i < clcf->error_pages->nelts; i++) { if (err_page[i].code == error) { - r->error_page = 1; + r->err_status = error; + r->err_ctx = r->ctx; return ngx_http_internal_redirect(r, &err_page[i].uri, NULL); } } diff --git a/src/os/unix/ngx_linux_config.h b/src/os/unix/ngx_linux_config.h index 11dbfac34..ca53a2306 100644 --- a/src/os/unix/ngx_linux_config.h +++ b/src/os/unix/ngx_linux_config.h @@ -35,6 +35,7 @@ #define SIZE_FMT "%d" #define SIZEX_FMT "%x" #define PID_FMT "%d" +#define TIME_FMT "%lu" diff --git a/src/os/unix/ngx_solaris_config.h b/src/os/unix/ngx_solaris_config.h index f94936dca..21724f80b 100644 --- a/src/os/unix/ngx_solaris_config.h +++ b/src/os/unix/ngx_solaris_config.h @@ -33,6 +33,7 @@ typedef uint32_t u_int32_t; #define SIZE_FMT "%d" #define SIZEX_FMT "%x" #define PID_FMT "%ld" +#define TIME_FMT "%lu" #ifndef HAVE_SELECT diff --git a/src/os/unix/ngx_time.c b/src/os/unix/ngx_time.c index bf3432ba7..37039918e 100644 --- a/src/os/unix/ngx_time.c +++ b/src/os/unix/ngx_time.c @@ -5,20 +5,22 @@ void ngx_localtime(ngx_tm_t *tm) { +#if (HAVE_LOCALTIME_R) + localtime_r(&ngx_cached_time, tm); +#else + ngx_tm_t *t; + + t = localtime(&ngx_cached_time); + *tm = *t; + +#endif + tm->ngx_tm_mon++; tm->ngx_tm_year += 1900; } -u_int ngx_msec(void) -{ - struct timeval tv; - - gettimeofday(&tv, NULL); - - return tv.tv_sec * 1000 + tv.tv_usec / 1000; -} #if 0 diff --git a/src/os/unix/ngx_time.h b/src/os/unix/ngx_time.h index cdec417e2..9dc4aea40 100644 --- a/src/os/unix/ngx_time.h +++ b/src/os/unix/ngx_time.h @@ -3,9 +3,13 @@ #include +#include + + +typedef uint64_t ngx_epoch_msec_t; typedef u_int ngx_msec_t; -#define NGX_MAX_MSEC (u_int) -1 +#define NGX_MAX_MSEC (ngx_msec_t) -1 typedef struct tm ngx_tm_t; @@ -17,16 +21,14 @@ typedef struct tm ngx_tm_t; #define ngx_tm_year tm_year #define ngx_tm_wday tm_wday -#define ngx_msleep(ms) usleep(ms * 1000) void ngx_localtime(ngx_tm_t *tm); -ngx_msec_t ngx_msec(void); +#define ngx_gettimeofday(tp) gettimeofday(tp, NULL); +#define ngx_msleep(ms) usleep(ms * 1000) -time_t ngx_time(); extern time_t ngx_cached_time; - #endif /* _NGX_TIME_H_INCLUDED_ */ diff --git a/src/os/win32/ngx_files.h b/src/os/win32/ngx_files.h index a29e333cc..0565eafa6 100644 --- a/src/os/win32/ngx_files.h +++ b/src/os/win32/ngx_files.h @@ -69,8 +69,8 @@ int ngx_file_type(char *filename, ngx_file_info_t *fi); #define ngx_file_uniq(fi) (*(ngx_file_uniq_t *) &fi.nFileIndexHigh) -/* There are 134774 days between 1 Jan 1970 and 1 Jan 1601, - 11644473600 seconds or 11644473600,000,000,0 100-nanosecond intervals */ + +/* 116444736000000000 is commented in src/os/win32/ngx_time.c */ #define ngx_file_mtime(fi) \ (time_t) (((((unsigned __int64) fi.ftLastWriteTime.dwHighDateTime << 32) \ diff --git a/src/os/win32/ngx_time.c b/src/os/win32/ngx_time.c new file mode 100644 index 000000000..8497c538d --- /dev/null +++ b/src/os/win32/ngx_time.c @@ -0,0 +1,29 @@ + +#include +#include + + +void ngx_gettimeofday(struct timeval *tp) +{ + uint64_t intervals; + FILETIME ft; + + GetSystemTimeAsFileTime(&ft); + + /* + * A file time is a 64-bit value that represents the number + * of 100-nanosecond intervals that have elapsed since + * 12:00 A.M. January 1, 1601 (UTC). + * + * Between January 1, 1970 (Epoch) and January 1, 1601 there are + * 134744 days, + * 11644473600 seconds or + * 11644473600,000,000,0 100-nanosecond intervals. + */ + + intervals = ((uint64_t) ft.dwHighDateTime << 32) | ft.dwLowDateTime; + intervals -= 116444736000000000; + + tp->tv_sec = intervals / 10000000; + tp->tv_usec = (intervals % 10000000) / 10; +} diff --git a/src/os/win32/ngx_time.h b/src/os/win32/ngx_time.h index 4cd84e564..36f8918fa 100644 --- a/src/os/win32/ngx_time.h +++ b/src/os/win32/ngx_time.h @@ -6,8 +6,10 @@ #include -typedef unsigned int ngx_msec_t; -#define NGX_MAX_MSEC ~0 +typedef uint64_t ngx_epoch_msec_t; + +typedef u_int ngx_msec_t; +#define NGX_MAX_MSEC (ngx_msec_t) -1 typedef SYSTEMTIME ngx_tm_t; @@ -23,10 +25,16 @@ typedef FILETIME ngx_mtime_t; #define ngx_msleep Sleep #define ngx_localtime GetLocalTime -#define ngx_msec GetTickCount -/* STUB */ -#define ngx_time() time(NULL) + +struct timeval { + long tv_sec; + long tv_usec; +}; + + +void ngx_gettimeofday(struct timeval *tp); + #endif /* _NGX_TIME_H_INCLUDED_ */