Win32 master/workers model

This commit is contained in:
Igor Sysoev 2009-04-20 06:08:47 +00:00
parent b533e98252
commit bd91999ea5
25 changed files with 1704 additions and 461 deletions

View file

@ -1,16 +1,5 @@
// Copyright (C) Igor Sysoev
#include <ngx_gui_resources.h>
nginx icon discardable "src\\os\\win32\\nginx.ico"
tray icon discardable "src\\os\\win32\\nginx_tray.ico"
nginx menu discardable
begin
popup "&nginx"
begin
menuitem "&Exit", NGX_WM_EXIT
menuitem "&About", NGX_WM_ABOUT
end
end

Binary file not shown.

Before

Width:  |  Height:  |  Size: 198 B

View file

@ -1,24 +0,0 @@
/* XPM */
static char * nginx_xpm[] = {
"16 16 2 2",
/* colors */
" c none",
"GG c #008000",
/* pixels */
" ",
" GGGGGGGGGGGGGGGG ",
" GGGGGGGGGGGGGGGG ",
" GGGGGGGGGGGGGGGGGGGG ",
" GGGGGG GGGGGG ",
" GGGGGG GGGGGG ",
" GGGGGG ",
" GGGGGG GGGGGGGGGGGGGGGG ",
" GGGGGG GGGGGGGGGGGGGGGGGG ",
" GGGGGG GGGGGGGGGGGGGG ",
" GGGGGG GGGGGG ",
" GGGGGG GGGGGG ",
" GGGGGGGGGGGGGGGGGGGG ",
" GGGGGGGGGGGGGGGG ",
" GGGGGGGGGGGGGGGG ",
" "
};

View file

@ -0,0 +1,116 @@
/*
* Copyright (C) Igor Sysoev
*/
#include <ngx_config.h>
#include <ngx_core.h>
#define NGX_MAX_ERROR_STR 2048
void ngx_cdecl
ngx_event_log(ngx_err_t err, const char *fmt, ...)
{
u_char *p, *last;
long types;
HKEY key;
HANDLE ev;
va_list args;
u_char text[NGX_MAX_ERROR_STR];
const char *msgarg[9];
static u_char netmsg[] = "%SystemRoot%\\System32\\netmsg.dll";
p = text + GetModuleFileName(NULL, (char *) text, NGX_MAX_ERROR_STR - 50);
*p++ = ':';
ngx_linefeed(p);
va_start(args, fmt);
p = ngx_vsnprintf(p, NGX_MAX_ERROR_STR, fmt, args);
va_end(args);
last = text + NGX_MAX_ERROR_STR;
if (err) {
if (p > last - 50) {
/* leave a space for an error code */
p = last - 50;
*p++ = '.';
*p++ = '.';
*p++ = '.';
}
p = ngx_snprintf(p, last - p, ((unsigned) err < 0x80000000)
? " (%d: " : " (%Xd: ", err);
p = ngx_strerror_r(err, p, last - p);
if (p < last) {
*p++ = ')';
}
}
if (p > last - NGX_LINEFEED_SIZE - 1) {
p = last - NGX_LINEFEED_SIZE - 1;
}
ngx_linefeed(p);
*p = '\0';
/*
* we do not log errors here since we use
* Event Log only to log our own logs open errors
*/
if (RegCreateKeyEx(HKEY_LOCAL_MACHINE,
"SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\nginx",
0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &key, NULL)
!= 0)
{
return;
}
if (RegSetValueEx(key, "EventMessageFile", 0, REG_EXPAND_SZ,
netmsg, sizeof(netmsg) - 1)
!= 0)
{
return;
}
types = EVENTLOG_ERROR_TYPE;
if (RegSetValueEx(key, "TypesSupported", 0, REG_DWORD,
(u_char *) &types, sizeof(long))
!= 0)
{
return;
}
RegCloseKey(key);
ev = RegisterEventSource(NULL, "nginx");
msgarg[0] = (char *) text;
msgarg[1] = NULL;
msgarg[2] = NULL;
msgarg[3] = NULL;
msgarg[4] = NULL;
msgarg[5] = NULL;
msgarg[6] = NULL;
msgarg[7] = NULL;
msgarg[8] = NULL;
/*
* the 3299 event id in netmsg.dll has the generic message format:
* "%1 %2 %3 %4 %5 %6 %7 %8 %9"
*/
ReportEvent(ev, EVENTLOG_ERROR_TYPE, 0, 3299, NULL, 9, 0, msgarg, NULL);
DeregisterEventSource(ev);
}

View file

@ -1,81 +0,0 @@
/*
* Copyright (C) Igor Sysoev
*/
#include <ngx_config.h>
#include <ngx_core.h>
#define NGX_MAX_TEXT 2048
void __cdecl
ngx_message_box(char *title, ngx_uint_t type, ngx_err_t err,
const char *fmt, ...)
{
va_list args;
u_char text[NGX_MAX_TEXT], *p, *last;
last = text + NGX_MAX_TEXT;
va_start(args, fmt);
p = ngx_vsnprintf(text, NGX_MAX_TEXT, fmt, args);
va_end(args);
if (err) {
if (p > last - 50) {
/* leave a space for an error code */
p = last - 50;
*p++ = '.';
*p++ = '.';
*p++ = '.';
}
p = ngx_snprintf(p, last - p, ((unsigned) err < 0x80000000)
? " (%d: " : " (%Xd: ", err);
p = ngx_strerror_r(err, p, last - p);
if (p < last) {
*p++ = ')';
}
}
if (p == last) {
p--;
}
*p = '\0';
MessageBox(NULL, (char *) text, title, type);
}
ngx_int_t
ngx_system_tray_icon(HWND window, u_long action, HICON icon, u_char *tip)
{
NOTIFYICONDATA ni;
ni.cbSize = sizeof(NOTIFYICONDATA);
ni.hWnd = window;
ni.uID = 0;
ni.uFlags = NIF_MESSAGE|NIF_ICON|NIF_TIP;
ni.uCallbackMessage = NGX_WM_TRAY;
ni.hIcon = icon;
if (tip) {
ngx_cpystrn((u_char *) ni.szTip, tip, 64);
} else {
ni.szTip[0] = '\0';
}
if (Shell_NotifyIcon(action, &ni) == 0) {
return NGX_ERROR;
}
return NGX_OK;
}

View file

@ -1,23 +0,0 @@
/*
* Copyright (C) Igor Sysoev
*/
#ifndef _NGX_GUI_H_INCLUDED_
#define _NGX_GUI_H_INCLUDED_
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_gui_resources.h>
void ngx_cdecl ngx_message_box(char *title, ngx_uint_t type, ngx_err_t err,
const char *fmt, ...);
ngx_int_t ngx_system_tray_icon(HWND window, u_long action,
HICON icon, u_char *tip);
#endif /* _NGX_GUI_H_INCLUDED_ */

View file

@ -1,19 +0,0 @@
/*
* Copyright (C) Igor Sysoev
*/
#ifndef _NGX_GUI_RESOURCES_H_INCLUDED_
#define _NGX_GUI_RESOURCES_H_INCLUDED_
#include <winuser.h>
#define NGX_WM_TRAY WM_USER
#define NGX_WM_EXIT WM_USER + 1
#define NGX_WM_ABOUT WM_USER + 2
#endif /* _NGX_GUI_RESOURCES_H_INCLUDED_ */

View file

@ -10,7 +10,6 @@
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_gui.h>
#define NGX_IO_SENDFILE 1
@ -40,11 +39,15 @@ ssize_t ngx_udp_wsarecv(ngx_connection_t *c, u_char *buf, size_t size);
ssize_t ngx_udp_overlapped_wsarecv(ngx_connection_t *c, u_char *buf,
size_t size);
ssize_t ngx_wsarecv_chain(ngx_connection_t *c, ngx_chain_t *chain);
ssize_t ngx_wsasend(ngx_connection_t *c, u_char *buf, size_t size);
ssize_t ngx_overlapped_wsasend(ngx_connection_t *c, u_char *buf, size_t size);
ngx_chain_t *ngx_wsasend_chain(ngx_connection_t *c, ngx_chain_t *in,
off_t limit);
ngx_chain_t *ngx_overlapped_wsasend_chain(ngx_connection_t *c, ngx_chain_t *in,
off_t limit);
void ngx_cdecl ngx_event_log(ngx_err_t err, const char *fmt, ...);
extern ngx_os_io_t ngx_os_io;
extern ngx_uint_t ngx_ncpu;
@ -57,6 +60,4 @@ extern ngx_fd_t ngx_stderr_fileno;
extern char ngx_unique[];
#endif /* _NGX_OS_H_INCLUDED_ */

View file

@ -8,12 +8,212 @@
#include <ngx_core.h>
int ngx_argc;
char **ngx_argv;
char **ngx_os_argv;
int ngx_argc;
char **ngx_argv;
char **ngx_os_argv;
ngx_int_t ngx_last_process;
ngx_process_t ngx_processes[NGX_MAX_PROCESSES];
ngx_pid_t ngx_execute(ngx_cycle_t *cycle, ngx_exec_ctx_t *ctx)
ngx_pid_t
ngx_spawn_process(ngx_cycle_t *cycle, char *name, ngx_int_t respawn)
{
return /* STUB */ 0;
u_long rc, n;
ngx_int_t s;
ngx_pid_t pid;
ngx_exec_ctx_t ctx;
char file[MAX_PATH + 1];
if (respawn >= 0) {
s = respawn;
} else {
for (s = 0; s < ngx_last_process; s++) {
if (ngx_processes[s].handle == NULL) {
break;
}
}
if (s == NGX_MAX_PROCESSES) {
ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
"no more than %d processes can be spawned",
NGX_MAX_PROCESSES);
return NGX_INVALID_PID;
}
}
n = GetModuleFileName(NULL, file, MAX_PATH);
if (n == 0) {
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
"GetModuleFileName() failed");
return NGX_INVALID_PID;
}
file[n] = '\0';
ngx_log_debug1(NGX_LOG_DEBUG_CORE, cycle->log, 0,
"GetModuleFileName: \"%s\"", file);
ctx.path = file;
ctx.name = name;
ctx.argv = NULL;
ctx.envp = NULL;
pid = ngx_execute(cycle, &ctx);
if (pid == NGX_INVALID_PID) {
return pid;
}
ngx_memzero(&ngx_processes[s], sizeof(ngx_process_t));
ngx_processes[s].handle = ctx.child;
ngx_processes[s].pid = pid;
ngx_processes[s].name = name;
ngx_sprintf(ngx_processes[s].term_event, "ngx_%s_term_%ul%Z", name, pid);
ngx_sprintf(ngx_processes[s].quit_event, "ngx_%s_quit_%ul%Z", name, pid);
ngx_sprintf(ngx_processes[s].reopen_event, "ngx_%s_reopen_%ul%Z",
name, pid);
rc = WaitForSingleObject(ngx_master_process_event, 5000);
ngx_time_update(0, 0);
ngx_log_debug1(NGX_LOG_DEBUG_CORE, cycle->log, 0,
"WaitForSingleObject: %ul", rc);
switch (rc) {
case WAIT_OBJECT_0:
ngx_processes[s].term = OpenEvent(EVENT_MODIFY_STATE, 0,
(char *) ngx_processes[s].term_event);
if (ngx_processes[s].term == NULL) {
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
"OpenEvent(\"%s\") failed",
ngx_processes[s].term_event);
goto failed;
}
ngx_processes[s].quit = OpenEvent(EVENT_MODIFY_STATE, 0,
(char *) ngx_processes[s].quit_event);
if (ngx_processes[s].quit == NULL) {
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
"OpenEvent(\"%s\") failed",
ngx_processes[s].quit_event);
goto failed;
}
ngx_processes[s].reopen = OpenEvent(EVENT_MODIFY_STATE, 0,
(char *) ngx_processes[s].reopen_event);
if (ngx_processes[s].reopen == NULL) {
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
"OpenEvent(\"%s\") failed",
ngx_processes[s].reopen_event);
goto failed;
}
if (ResetEvent(ngx_master_process_event) == 0) {
ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
"ResetEvent(\"%s\") failed",
ngx_master_process_event_name);
goto failed;
}
break;
case WAIT_TIMEOUT:
ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
"the event \"%s\" was not signaled for 5s",
ngx_master_process_event_name);
goto failed;
case WAIT_FAILED:
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
"WaitForSingleObject(\"%s\") failed",
ngx_master_process_event_name);
goto failed;
}
if (respawn >= 0) {
return pid;
}
switch (respawn) {
case NGX_PROCESS_RESPAWN:
ngx_processes[s].just_respawn = 0;
break;
case NGX_PROCESS_JUST_RESPAWN:
ngx_processes[s].just_respawn = 1;
break;
}
if (s == ngx_last_process) {
ngx_last_process++;
}
return pid;
failed:
if (ngx_processes[s].reopen) {
ngx_close_handle(ngx_processes[s].reopen);
}
if (ngx_processes[s].quit) {
ngx_close_handle(ngx_processes[s].quit);
}
if (ngx_processes[s].term) {
ngx_close_handle(ngx_processes[s].term);
}
TerminateProcess(ngx_processes[s].handle, 2);
if (ngx_processes[s].handle) {
ngx_close_handle(ngx_processes[s].handle);
}
return NGX_INVALID_PID;
}
ngx_pid_t
ngx_execute(ngx_cycle_t *cycle, ngx_exec_ctx_t *ctx)
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
ngx_memzero(&si, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
ngx_memzero(&pi, sizeof(PROCESS_INFORMATION));
if (CreateProcess(ctx->path, /* STUB */ NULL,
NULL, NULL, 0, CREATE_NO_WINDOW, NULL, NULL, &si, &pi)
== 0)
{
ngx_log_error(NGX_LOG_CRIT, cycle->log, ngx_errno,
"CreateProcess(\"%s\") failed", ngx_argv[0]);
return 0;
}
ctx->child = pi.hProcess;
if (CloseHandle(pi.hThread) == 0) {
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
"CloseHandle(pi.hThread) failed");
}
ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0,
"start %s process %P", ctx->name, pi.dwProcessId);
return pi.dwProcessId;
}

View file

@ -8,38 +8,71 @@
#define _NGX_PROCESS_H_INCLUDED_
typedef DWORD ngx_pid_t;
#define NGX_INVALID_PID 0
typedef DWORD ngx_pid_t;
#define NGX_INVALID_PID 0
#define ngx_getpid GetCurrentProcessId
#define ngx_log_pid ngx_pid
#define ngx_getpid GetCurrentProcessId
#define ngx_log_pid ngx_pid
#define NGX_PROCESS_SYNC_NAME \
(sizeof("ngx_cache_manager_mutex_") + NGX_INT32_LEN)
typedef struct {
char *path;
char *name;
char *const *argv;
char *const *envp;
HANDLE handle;
ngx_pid_t pid;
char *name;
HANDLE term;
HANDLE quit;
HANDLE reopen;
u_char term_event[NGX_PROCESS_SYNC_NAME];
u_char quit_event[NGX_PROCESS_SYNC_NAME];
u_char reopen_event[NGX_PROCESS_SYNC_NAME];
unsigned just_respawn:1;
unsigned exiting:1;
} ngx_process_t;
typedef struct {
char *path;
char *name;
char *const *argv;
char *const *envp;
HANDLE child;
} ngx_exec_ctx_t;
#define NGX_PROCESS_SINGLE 0
#define NGX_PROCESS_MASTER 1
#define NGX_PROCESS_WORKER 2
#define NGX_PROCESS_SINGLE 0
#define NGX_PROCESS_MASTER 1
#define NGX_PROCESS_WORKER 2
ngx_pid_t ngx_spawn_process(ngx_cycle_t *cycle, char *name, ngx_int_t respawn);
ngx_pid_t ngx_execute(ngx_cycle_t *cycle, ngx_exec_ctx_t *ctx);
#define ngx_debug_point()
#define ngx_sched_yield() Sleep(0)
#define ngx_sched_yield() Sleep(0)
extern int ngx_argc;
extern char **ngx_argv;
extern char **ngx_os_argv;
#define NGX_MAX_PROCESSES (MAXIMUM_WAIT_OBJECTS - 4)
extern ngx_pid_t ngx_pid;
#define NGX_PROCESS_RESPAWN -2
#define NGX_PROCESS_JUST_RESPAWN -3
extern int ngx_argc;
extern char **ngx_argv;
extern char **ngx_os_argv;
extern ngx_int_t ngx_last_process;
extern ngx_process_t ngx_processes[NGX_MAX_PROCESSES];
extern ngx_pid_t ngx_pid;
#endif /* _NGX_PROCESS_H_INCLUDED_ */

File diff suppressed because it is too large Load diff

View file

@ -12,30 +12,33 @@
#include <ngx_core.h>
#define NGX_PROCESS_SINGLE 0
#define NGX_PROCESS_MASTER 1
#define NGX_PROCESS_WORKER 2
#define NGX_PROCESS_SINGLE 0
#define NGX_PROCESS_MASTER 1
#define NGX_PROCESS_WORKER 2
#define NGX_PROCESS_SIGNALLER 3
void ngx_master_process_cycle(ngx_cycle_t *cycle);
void ngx_single_process_cycle(ngx_cycle_t *cycle);
ngx_int_t ngx_signal_process(ngx_cycle_t *cycle, char *sig);
void ngx_close_handle(HANDLE h);
extern ngx_uint_t ngx_process;
extern ngx_pid_t ngx_pid;
extern ngx_pid_t ngx_new_binary;
extern ngx_uint_t ngx_inherited;
extern ngx_uint_t ngx_threaded;
extern ngx_uint_t ngx_exiting;
extern sig_atomic_t ngx_reap;
extern sig_atomic_t ngx_timer;
extern sig_atomic_t ngx_quit;
extern sig_atomic_t ngx_terminate;
extern sig_atomic_t ngx_noaccept;
extern sig_atomic_t ngx_reconfigure;
extern sig_atomic_t ngx_reopen;
extern sig_atomic_t ngx_change_binary;
extern ngx_uint_t ngx_inherited;
extern ngx_pid_t ngx_new_binary;
extern HANDLE ngx_master_process_event;
extern char ngx_master_process_event_name[];
#endif /* _NGX_PROCESS_CYCLE_H_INCLUDED_ */

View file

@ -18,11 +18,14 @@ ngx_err_t
ngx_create_thread(ngx_tid_t *tid,
ngx_thread_value_t (__stdcall *func)(void *arg), void *arg, ngx_log_t *log)
{
u_long id;
ngx_err_t err;
*tid = CreateThread(NULL, stack_size, func, arg, 0, NULL);
*tid = CreateThread(NULL, stack_size, func, arg, 0, &id);
if (*tid != NULL) {
ngx_log_error(NGX_LOG_NOTICE, log, 0,
"create thread " NGX_TID_T_FMT, id);
return 0;
}

View file

@ -24,7 +24,7 @@ ngx_os_io_t ngx_os_io = {
ngx_wsarecv,
ngx_wsarecv_chain,
ngx_udp_wsarecv,
NULL,
ngx_wsasend,
ngx_wsasend_chain,
0
};
@ -56,7 +56,8 @@ static GUID cx_guid = WSAID_CONNECTEX;
static GUID dx_guid = WSAID_DISCONNECTEX;
ngx_int_t ngx_os_init(ngx_log_t *log)
ngx_int_t
ngx_os_init(ngx_log_t *log)
{
DWORD bytes;
SOCKET s;
@ -207,7 +208,7 @@ ngx_int_t ngx_os_init(ngx_log_t *log)
ngx_close_socket_n " failed");
}
if (GetEnvironmentVariable("nginx_unique", ngx_unique, NGX_INT32_LEN + 1)
if (GetEnvironmentVariable("ngx_unique", ngx_unique, NGX_INT32_LEN + 1)
!= 0)
{
ngx_process = NGX_PROCESS_WORKER;
@ -217,7 +218,7 @@ ngx_int_t ngx_os_init(ngx_log_t *log)
if (err != ERROR_ENVVAR_NOT_FOUND) {
ngx_log_error(NGX_LOG_EMERG, log, err,
"GetEnvironmentVariable(\"nginx_unique\") failed");
"GetEnvironmentVariable(\"ngx_unique\") failed");
return NGX_ERROR;
}
@ -228,7 +229,8 @@ ngx_int_t ngx_os_init(ngx_log_t *log)
}
void ngx_os_status(ngx_log_t *log)
void
ngx_os_status(ngx_log_t *log)
{
ngx_osviex_stub_t *osviex_stub;

183
src/os/win32/ngx_wsasend.c Normal file
View file

@ -0,0 +1,183 @@
/*
* Copyright (C) Igor Sysoev
*/
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_event.h>
ssize_t
ngx_wsasend(ngx_connection_t *c, u_char *buf, size_t size)
{
int n;
u_long sent;
ngx_err_t err;
ngx_event_t *wev;
WSABUF wsabuf;
wev = c->write;
if (!wev->ready) {
return NGX_AGAIN;
}
/*
* WSABUF must be 4-byte aligned otherwise
* WSASend() will return undocumented WSAEINVAL error.
*/
wsabuf.buf = (char *) buf;
wsabuf.len = size;
sent = 0;
n = WSASend(c->fd, &wsabuf, 1, &sent, 0, NULL, NULL);
ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0,
"WSASend: fd:%d, %d, %ul of %uz", c->fd, n, sent, size);
if (n == 0) {
if (sent < size) {
wev->ready = 0;
}
c->sent += sent;
return sent;
}
err = ngx_socket_errno;
if (err == WSAEWOULDBLOCK) {
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err, "WSASend() not ready");
return NGX_AGAIN;
}
wev->error = 1;
ngx_connection_error(c, err, "WSASend() failed");
return NGX_ERROR;
}
ssize_t
ngx_overlapped_wsasend(ngx_connection_t *c, u_char *buf, size_t size)
{
int n;
u_long sent;
ngx_err_t err;
ngx_event_t *wev;
LPWSAOVERLAPPED ovlp;
WSABUF wsabuf;
wev = c->write;
if (!wev->ready) {
return NGX_AGAIN;
}
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
"wev->complete: %d", wev->complete);
if (!wev->complete) {
/* post the overlapped WSASend() */
/*
* WSABUFs must be 4-byte aligned otherwise
* WSASend() will return undocumented WSAEINVAL error.
*/
wsabuf.buf = (char *) buf;
wsabuf.len = size;
sent = 0;
ovlp = (LPWSAOVERLAPPED) &c->write->ovlp;
ngx_memzero(ovlp, sizeof(WSAOVERLAPPED));
n = WSASend(c->fd, &wsabuf, 1, &sent, 0, ovlp, NULL);
ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0,
"WSASend: fd:%d, %d, %ul of %uz", c->fd, n, sent, size);
wev->complete = 0;
if (n == 0) {
if (ngx_event_flags & NGX_USE_IOCP_EVENT) {
/*
* if a socket was bound with I/O completion port then
* GetQueuedCompletionStatus() would anyway return its status
* despite that WSASend() was already complete
*/
wev->active = 1;
return NGX_AGAIN;
}
if (sent < size) {
wev->ready = 0;
}
c->sent += sent;
return sent;
}
err = ngx_socket_errno;
if (err == WSA_IO_PENDING) {
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
"WSASend() posted");
wev->active = 1;
return NGX_AGAIN;
}
wev->error = 1;
ngx_connection_error(c, err, "WSASend() failed");
return NGX_ERROR;
}
/* the overlapped WSASend() complete */
wev->complete = 0;
wev->active = 0;
if (ngx_event_flags & NGX_USE_IOCP_EVENT) {
if (wev->ovlp.error) {
ngx_connection_error(c, wev->ovlp.error, "WSASend() failed");
return NGX_ERROR;
}
sent = wev->available;
} else {
if (WSAGetOverlappedResult(c->fd, (LPWSAOVERLAPPED) &wev->ovlp,
&sent, 0, NULL)
== 0)
{
ngx_connection_error(c, ngx_socket_errno,
"WSASend() or WSAGetOverlappedResult() failed");
return NGX_ERROR;
}
}
ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
"WSAGetOverlappedResult: fd:%d, %ul of %uz",
c->fd, sent, size);
if (sent < size) {
wev->ready = 0;
}
c->sent += sent;
return sent;
}