Fix windows issue with multiple workers

Sergey Brester serg.brester at sebres.de
Wed Jun 17 07:58:46 UTC 2015


Hi,

Yes, for exactly one child process...

For example, same (modified for multiprocessing) code does not work on 
my mashine (win7 x64) for 2nd (3th etc.) process (with error 10022 = 
INVARG). I think the handle schould be then duplicated, and see MSDN 
(https://msdn.microsoft.com/en-us/library/windows/desktop/ms724251.aspx)

Sockets. No error is returned, but the duplicate handle may not be 
recognized by Winsock at the target process. Also, using DuplicateHandle 
interferes with internal reference counting on the underlying object. To 
duplicate a socket handle, use the WSADuplicateSocket function.

Regards,
sebres.

.

Am 17.06.2015 04:27, schrieb Maxim Dounin:

> Hello!
> 
> On Wed, Jun 10, 2015 at 09:48:28PM +0200, Sergey Brester wrote:
> 
> [...]
> 
>> @Maxim Dounin: 1) your suggested way with shared handle and 
>> bInheritHandle does not work, because of: [quote] Sockets. No error is 
>> returned, but the duplicate handle may not be recognized by Winsock at 
>> the target process. Also, using DUPLICATEHANDLE interferes with 
>> internal reference counting on the underlying object. To duplicate a 
>> socket handle, use the WSADUPLICATESOCKET function. [/quote]
> 
> The quote is from DuplicateHandle() description, which is
> irrelevant to the approach suggested. Sockets are inheritable
> between processes, including listen ones.
> 
> Simple test code below, as adapted from the accept() MSDN example,
> demonstrates that the approach is working.
> 
> #include <winsock2.h>
> #include <stdio.h>
> #include <windows.h>
> 
> #pragma comment(lib, "Ws2_32.lib")
> 
> int
> main(int argc, char *argv[])
> {
> int rc;
> u_long code;
> SOCKET listen_socket, s;
> WSADATA wsaData;
> struct sockaddr_in sin;
> STARTUPINFO si;
> PROCESS_INFORMATION pi;
> char command[256];
> 
> rc = WSAStartup(MAKEWORD(2, 2), &wsaData);
> if (rc != NO_ERROR) {
> printf("WSAStartup() failed: %dn", rc);
> return 2;
> }
> 
> if (argc == 2) {
> listen_socket = atoi(argv[1]);
> printf("Inherited socket: %dn", listen_socket);
> goto accept;
> }
> 
> listen_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
> if (listen_socket == INVALID_SOCKET) {
> printf("socket failed with error: %ldn", WSAGetLastError());
> return 1;
> }
> 
> printf("Listen socket: %dn", listen_socket);
> 
> sin.sin_family = AF_INET;
> sin.sin_addr.s_addr = inet_addr("127.0.0.1");
> sin.sin_port = htons(8080);
> 
> if (bind(listen_socket, (SOCKADDR *) &sin, sizeof(sin)) == 
> SOCKET_ERROR) {
> printf("bind() failed: %ldn", WSAGetLastError());
> return 1;
> }
> 
> if (listen(listen_socket, 1) == SOCKET_ERROR) {
> printf("listen() failed: %ldn", WSAGetLastError());
> return 1;
> }
> 
> if (argc == 1) {
> ZeroMemory(&si, sizeof(si));
> si.cb = sizeof(si);
> ZeroMemory(&pi, sizeof(pi));
> 
> _snprintf(command, sizeof(command), "%s %d", argv[0], listen_socket);
> 
> if (CreateProcess(NULL, command,
> NULL, NULL, 1, 0, NULL, NULL,
> &si, &pi)
> == 0)
> {
> printf("CreateProcess() failed: %ldn", GetLastError());
> return 1;
> }
> 
> WaitForSingleObject(pi.hProcess, INFINITE);
> 
> if (GetExitCodeProcess(pi.hProcess, &code) == 0) {
> printf("GetExitCodeProcess() failed: %ldn", GetLastError());
> return 1;
> }
> 
> printf("Child process exited: %dn", code);
> 
> CloseHandle(pi.hProcess);
> CloseHandle(pi.hThread);
> }
> 
> accept:
> 
> printf("Waiting for client to connect...n");
> 
> s = accept(listen_socket, NULL, NULL);
> if (s == INVALID_SOCKET) {
> printf("accept() failed: %ldn", WSAGetLastError());
> return 1;
> }
> 
> printf("Client connectedn");
> 
> return 0;
> }



More information about the nginx-devel mailing list