Перенаправлени stdio дочернего процесса на сокеты + LSP
От: Andrew S Россия http://alchemy-lab.com
Дата: 19.07.05 15:23
Оценка:
Всем привет.

Вкратце опишу проблему. Есть дочерний процесс, консольный. Ему надо перенаправить вывод stdout в сокет. Очевидно, это делается довольно просто (надо создавать сокет через WSASocket, затем DuplicateHandle, дабы разрешить наследование на 9х, ну а далее все как обычно, используя полученный хендл в качестве stdout при создании дочернего процесса). Это все сделано и работает — как на 9х, так и на NT. Однако в процессе обнаружились следующие моменты — здесь и здесь. Вкратце — если установлены LSP, то DuplicateHandle может вернуть некорректный сокет, причем отследить сам вызов DuplicateHandle в LSP (т.е. каким-либо образом скорректировать проблему), невозможно.
Вопрос в следующем — так ли это? Ну или на крайний случай порекомендуйте, какое либо приложение, которое устанавливает свой LSP, дабы проверить сий прискорбный факт. Ну и еще вопрос вдогонку — как оказалось, создать сокет, подходящий для stdout можно только при помощи WSASocket, либо установкой setsockopt( SO_OPENTYPE) в значение, отличное от нуля (например, SO_SYNCHRONOUS_NONALERT). Причем оба варианта приводят к шваху при использовании LSP (Q189171). Уж очень не хочется принимать stdout в пайп, а затем это все передавать в сокет, уж больно глупо как то... да и сложнее — придется отдельные треды на прием\передачу делать, чего бы не хотелось..
В общем, всем заранее спасибо за советы.
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re: Перенаправлени stdio дочернего процесса на сокеты + LSP
От: TarasCo  
Дата: 19.07.05 15:58
Оценка: 18 (1)
Здравствуйте, Andrew S, Вы писали:

AS>Всем привет.


AS>Вкратце опишу проблему. Есть дочерний процесс, консольный. Ему надо перенаправить вывод stdout в сокет. Очевидно, это делается довольно просто (надо создавать сокет через WSASocket, затем DuplicateHandle, дабы разрешить наследование на 9х, ну а далее все как обычно, используя полученный хендл в качестве stdout при создании дочернего процесса). Это все сделано и работает — как на 9х, так и на NT. Однако в процессе обнаружились следующие моменты — здесь и здесь. Вкратце — если установлены LSP, то DuplicateHandle может вернуть некорректный сокет, причем отследить сам вызов DuplicateHandle в LSP (т.е. каким-либо образом скорректировать проблему), невозможно.

AS>Вопрос в следующем — так ли это? Ну или на крайний случай порекомендуйте, какое либо приложение, которое устанавливает свой LSP, дабы проверить сий прискорбный факт. Ну и еще вопрос вдогонку — как оказалось, создать сокет, подходящий для stdout можно только при помощи WSASocket, либо установкой setsockopt( SO_OPENTYPE) в значение, отличное от нуля (например, SO_SYNCHRONOUS_NONALERT). Причем оба варианта приводят к шваху при использовании LSP (Q189171). Уж очень не хочется принимать stdout в пайп, а затем это все передавать в сокет, уж больно глупо как то... да и сложнее — придется отдельные треды на прием\передачу делать, чего бы не хотелось..
AS>В общем, всем заранее спасибо за советы.

LSP фильтры могут создавать дескрипторы двух видов: IFS и non IFS. Первые являются нормальными дескрипторами. Их можно использовать в файловых операциях и можно дублировать с помощью DuplicateHandle. Но в этом случае вызовы ReadFile/WriteFile пойдут мимо LSP фильтра, клиент будет работать напрямую с ядром. Разработчикам LSP фильтров така ситуация не нравится , поэтому они используют обычно non IFS дескрипторы. Это просто числа, они не являются дескрипторами и имеют смысл только для LSP провайдера. В принципе, такие дескриторы можно дублировать с помощью WSADuplicateSocket, но это не решает проблемы — в сокет с non IFS нельзя перенаправить ввод/вывод с консоли.

Могу посоветовать использовать WSASocket c заполненной струтурой WSAPROTOCOL_INFO, где указать флаг XP1_IFS_HANDLES

PS: если поможет, шлите пиво ))))))))))
Да пребудет с тобою сила
Re[2]: Перенаправлени stdio дочернего процесса на сокеты + L
От: Andrew S Россия http://alchemy-lab.com
Дата: 19.07.05 16:29
Оценка:
TC>Могу посоветовать использовать WSASocket c заполненной струтурой WSAPROTOCOL_INFO, где указать флаг XP1_IFS_HANDLES

Про IFS\не IFS я уже тоже начитался. А вот перебрать провайдеров и найти подходящего для протокола как то не догадался. Да, по-видимому, только этот вариант. Либо пайпы в качестве промежуточного буфера, чего активно не хочется — там будут как минимум проблемы с прерыванием блокирующих чтений\записей...

TC>PS: если поможет, шлите пиво ))))))))))


Пиво, наверное, не получится, а вот оценку с удовольствием поставлю. Спасибо!
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re: Перенаправлени stdio дочернего процесса на сокеты + LSP
От: Andrew S Россия http://alchemy-lab.com
Дата: 19.07.05 17:19
Оценка:
Может, кому пригодится....

SOCKET ifs_socket(int af, int type, int protocol) 
{ 
    unsigned long proto_buffers_len = 4096; 
    SOCKET out = INVALID_SOCKET;
    int nProtocols[] = {protocol, 0};
    WSAPROTOCOL_INFO *pInfo = NULL;
    while (TRUE) 
    {
        pInfo = (WSAPROTOCOL_INFO *)realloc(pInfo, proto_buffers_len);
        int nResult = ::WSAEnumProtocols(nProtocols, pInfo, &proto_buffers_len);
        if (nResult != SOCKET_ERROR)
        {
            for (int i = 0; i < nResult; ++i) 
            { 
                WSAPROTOCOL_INFOA proto_info; 
 
                if (
                    ((af == AF_UNSPEC) || (af == pInfo[i].iAddressFamily)) &&
                    (type == pInfo[i].iSocketType)
                   )
                {
                    out = ::WSASocket(af, type, protocol, &pInfo[i], 0, 0); 
                    break; 
                }
            } 
            break;
        } 
        if (::WSAGetLastError() != WSAENOBUFS)
            break;
    } 
    free(pInfo);
    return out; 
}
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[2]: Перенаправлени stdio дочернего процесса на сокеты + L
От: Andrew S Россия http://alchemy-lab.com
Дата: 19.07.05 19:32
Оценка: 12 (2)
Гм, вот корректный вариант.
SOCKET ifs_socket(int af, int type, int protocol) 
{ 
    unsigned long proto_buffers_len = 4096; 
    SOCKET out = INVALID_SOCKET;
    int nProtocols[] = {protocol, 0};
    WSAPROTOCOL_INFO *pInfo = NULL;
    while ((pInfo = (WSAPROTOCOL_INFO *)realloc(pInfo, proto_buffers_len))) 
    {
        int nResult = ::WSAEnumProtocols(nProtocols, pInfo, &proto_buffers_len);
        if (nResult != SOCKET_ERROR)
        {
            for (int i = 0; i < nResult; ++i) 
                if (
                    ((af == AF_UNSPEC) || (af == pInfo[i].iAddressFamily)) &&
                    (type == pInfo[i].iSocketType) &&
                    (pInfo[i].dwServiceFlags1 & XP1_IFS_HANDLES)
                   )
                {
                    out = ::WSASocket(af, type, protocol, &pInfo[i], 0, 0); 
                    break; 
                }
            break;
        } 
        if (::WSAGetLastError() != WSAENOBUFS)
            break;
    } 
    free(pInfo);
    return out; 
}
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re: Перенаправлени stdio дочернего процесса на сокеты + LSP
От: Andrew S Россия http://alchemy-lab.com
Дата: 27.07.05 10:31
Оценка: 4 (1)
Всем привет еще раз.
Возник еще один вопрос по этой же тематике.
Перенаправление оутпута на IFS сокет вполне работает. Но, оказывается, не всегда. По крайней мере, я не смог добиться работы при следующих условиях
1. Система: Windows 95 osr2 + winsock2.2 update
2. Дочерний процесс: не консольный, однако пишет в stdout

В nt-based системах все работает нормально во всех случаях. Если на 95-эх вместо (2) подсунуть именно консольное приложение (т.е. у которого во флагах PE указано что оно консольное), то все работает и в 95-х. Если вместо сокетов пользовать пайпы, то неконсольное работает и в 95-х.
Есть какие предположения, уже больно странно то, что поведение различается в случае gui и не gui дочернего процесса только на 9х системах, причем на пайпах там работает в обоих случаях нормально.. Я в смятении
Q150523 вообще утверждает, что сокеты нальзя ставить как стандартые хендлы для дочерних процессов в Windows 9х, но это явно не так — для консольных приложений все работает...
http://www.rusyaz.ru/pr — стараемся писАть по-русски
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.