Pipes - WaitNamedPipes examples are confusing (MSDN and others) - named-pipes

Can someone explain WaitNamedPipe for me? Using the examples on MSDN and elsewhere it doesn't seem to be as suggested. Using it in a different order does work.
In the examples, the client does
CreateFile (Pipe)
WaitNamedPipe
WriteFile
(Flushbuffers, CloseHandle)
Now for me, WaitNamedFile always times out unless I
WaitNamedFile
CreateFile
WriteFile
(Flushbuffers, CloseHandle)
Server -
hPipe = CreateNamedPipe(TEXT(HELPPIPE),
PIPE_ACCESS_INBOUND,
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
1,
PIPEBUFFERSIZE,
PIPEBUFFERSIZE,
NMPWAIT_USE_DEFAULT_WAIT,
NULL);
and
while (!g_Quit)
{
if (ConnectNamedPipe(hPipe, NULL)) // wait for someone to connect to the pipe
{
char buffer[PIPEBUFFERSIZE];
DWORD dwRead;
while (ReadFile(hPipe, buffer, sizeof(buffer) - 1, &dwRead, NULL))
{
// add terminating zero
buffer[dwRead] = '\0';
if (!processHelpCommand(buffer))
{
g_Quit = true;
}
}
}
DisconnectNamedPipe(hPipe);
}
Client -
if (WaitNamedPipe (TEXT(HELPPIPE), 2000))
{
hPipe = CreateFile(TEXT(HELPPIPE),
GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
0,
NULL);
if (hPipe != INVALID_HANDLE_VALUE)
{
if (WriteFile(hPipe,
commandLine,
strlen (commandLine) + 1,
&dwWritten,
NULL))
{
success = TRUE;
}
}
FlushFileBuffers(hPipe);
CloseHandle(hPipe);
}
The MSDN example is here
A few other on stackoverflow and elsewhere

Or is it that I've misunderstood the MSDN exmaple ;-)
I think I've answered my own question.

Related

Under what circumstances, if any, can ReadFile hang after WSAEventSelect said it was ready?

This is rather ugly. We're getting weird hangups caused (read: triggered) by some security scanning software. I suspect it has a nonstandard TCP/IP stack, and the customer is asking why hangups.
Static analysis suggests only two possible locations for the hangup. The hangup either has to be in ReadFile() or WriteFile() on a socket; and WriteFile() cannot hang here unless the scanner is designed to make WriteFile() hang by setting the window size to zero. If WriteFile() were to return at all even if it didn't make progress I'd be able to knock the thing out of its wedged state. I also don't think the log state is consistent with WriteFile() returning.
So onto ReadFile(): this is the calling sequence:
SOCKET conn;
HANDLE unwedgeEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
HANDLE listenEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if (listenEvent == NULL) return;
//...
conn = accept(lstn);
for (;;) {
HANDLE wakeup[2];
wakeup[0] = unwedgeEvent;
wakeup[1] = listenEvent;
if (WSAEventSelect(conn, socket, FD_READ | FD_CLOSE) == 0) {
// Log error
break;
}
which = WaitForMultipleObjects(2, wakeup, FALSE, INFINITE);
if (which < 0) {
// Log error
break;
}
if (which == 1) {
DWORD read;
r = ReadFile(conn, chunk, 4096, &read, NULL);
if (r == 0) {
// Handle error -- not stuck here
} else {
// Handle data -- not stuck here either
}
}
if (which == 0) break;
}
Where signalling unwedgeEvent doesn't manage to accomplish anything and the thread remains stuck forever.
So the real question is have I gone nuts or is this really a thing that can happen?
So this has gone somewhat off the deep end; I don't need non-blocking sockets at all. I need a select() that takes handle arguments to things that are sockets and things that are not sockets.
The following API sequences do not hang in ReadFile:
---------------------------------------------------------------
Sender B Receiver
WSAEventSelect
* WaitForMultipeObjects
send(buffer size = 1)
ReadFile(size = 1)
WSAEventSelect
* WaitForMultipeObjects
send(buffer size = 1)
ReadFile(size = 1)
................................................................
WSAEventSelect
* WaitForMultipeObjects
send(buffer size = 2)
ReadFile(size = 1)
WaitForMultipeObjects
ReadFile(size = 1)
................................................................
WSAEventSelect
* WaitForMultipeObjects
send(buffer size = 1)
send(buffer size = 1)
ReadFile(size = 1)
WaitForMultipeObjects
ReadFile(size = 1)
................................................................
WSAEventSelect
send(buffer size = 1)
WaitForMultipeObjects
send(buffer size = 1)
ReadFile(size = 1)
WaitForMultipeObjects
ReadFile(size = 1)
................................................................
WSAEventSelect
send(buffer size = 1)
WaitForMultipeObjects
send(buffer size = 1)
ReadFile(size = 2)
* WaitForMultipeObjects
send(buffer size = 1)
ReadFile(size = 1)
................................................................
WSAEventSelect
send(buffer size = 1)
WaitForMultipeObjects
ReadFile(size = 1)
send(buffer size = 1)
WaitForMultipeObjects
ReadFile(size = 1)
I see a number of issues with your code:
You should use WSACreateEvent() and WSAWaitForMultipleEvents() instead of CreateEvent() and WaitForMultipleObjects(). Although the current implementation is that the former APIs simply map to the latter APIs, Microsoft is free to change that implementation at any time without breaking code that uses the former APIs properly.
In your call to WSAEventSelect(), socket should be listenEvent instead.
WSAEventSelect() returns SOCKET_ERROR (-1) on failure, not 0 like you have coded.
You are not calling WSAEnumNetworkEvents() at all, which you need to do in order to determine if FD_READ was the actual type of event triggered, and to clear the socket's event state and reset the event object. So, you may be acting on a stale read state, which could explain why you end up calling ReadFile() when there is actually nothing available to read.
WSAEventSelect() puts the socket into non-blocking mode (per its documentation), so it is actually not possible for ReadFile() (or any other reading function) to block on the socket. However, it could fail immediately with a WSAEWOULDBLOCK error, so make sure you are not treating that condition as a fatal error.
The WSAEventSelect() documentation does not list ReadFile() as a supported function for re-enabling events when calling WSAEnumNetworkEvents(). Although the Socket Handles documentation does say that a Winsock SOCKET can be used with non-Winsock I/O functions like ReadFile(), it recommends that a SOCKET should only be used with Winsock functions. So, you should use send()/recv() or WSASend()/WSARecv() instead of WriteFile()/ReadFile().
With that said, try something more like the following:
HANDLE unwedgeEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (unwedgeEvent == NULL) {
// Log error
return;
}
...
SOCKET conn = accept(lstn, NULL, NULL);
if (conn == INVALID_SOCKET) {
// Log error
return;
}
...
WSAEVENT listenEvent = WSACreateEvent();
if (listenEvent == NULL) {
// Log error
}
else if (WSAEventSelect(conn, listenEvent, FD_READ | FD_CLOSE) == SOCKET_ERROR) {
// Log error
}
else {
WSAEVENT wakeup[2];
wakeup[0] = (WSAEVENT) unwedgeEvent;
wakeup[1] = listenEvent;
char chunk[4096];
int read;
do {
DWORD which = WSAWaitForMultipleEvents(2, wakeup, FALSE, WSA_INFINITE, FALSE);
if (which == WSA_WAIT_FAILED) {
// Log error
break;
}
if (which == WSA_WAIT_EVENT_0) {
break;
}
if (which == (WSA_WAIT_EVENT_0+1)) {
WSANETWORKEVENTS events = {};
if (WSAEnumNetworkEvents(conn, listenEvent, &events) == SOCKET_ERROR) {
// Log error
break;
}
if (events.lNetworkEvents & FD_READ) {
read = recv(conn, chunk, sizeof(chunk), 0);
if (read == SOCKET_ERROR) {
if (WSAGetLastError() != WSAEWOULDBLOCK) {
// Log error
break;
}
}
else if (read == 0) {
break;
}
else {
// Handle chunk up to read number of bytes
}
}
if (events.lNetworkEvents & FD_CLOSE) {
break;
}
}
}
while (true);
WSACloseEvent(listenEvent);
}
closesocket(conn);

OPC server is always NULL

when I use CoCreateInstanceEx I always get NULL as a result.
My code is like that:
bool Connect(Str a_sServerName, COSERVERINFO* CoServerInfo)
{
CLSID CLSID_OPCServer;
HRESULT hr;
hr = CLSIDFromString(a_sServerName, &CLSID_OPCServer);
if( hr == S_FALSE )
{
// Log string "Wrong CLSID of OPC server"
return false;
}
LONG cmq = 1; // nbr of class instance to create.
MULTI_QI queue[] = { { &IID_IOPCServer, nullptr, 0 } };
// HERE IS SOMETHING WRONG WITH THE queue VARIABLE
hr = CoCreateInstanceEx(CLSID_OPCServer, NULL, CLSCTX_ALL, CoServerInfo, cmq, queue);
if( hr == S_FALSE )
{
// Log string "Error creating OPC server instance"
return false;
}
else
{
// Log string "Successful connection to the OPC server"
}
pIOPCServer = (IOPCServer*) queue[0].pItf;
//AND HERE pIOPCServer IS NULL
}
I get no errors, everything seem to work properly. But unfortunately the pIOPCServer is NULL.
Don't you suspect what could be wrong here?
For any help great thanks in advance.
Best Regards,
You need to check not just the HRESULT from CoCreateInstanceEx, but also the HRESULT in queue[0].hr. The reason of the problem will most likely be there.

How do I resolve code.org's App Lab readRecord() asynchronous timing?

I'm a fairly new student in AP CSP, and I wanted to create a username/password system in code.org's App Lab, however, it requires me to get the readRecords() command to function first.
I have the code as such :
function read (array) {
var truth;
readRecords("loginarray", {}, function(records) {
if (records.length > 0) {
for (var i = 0; i < records.length; i++){
if (array.user == records[i].user){
if (array.pass == records[i].pass) {
truth = false;
hideElement("unverifiedtext");
hideElement("retrybutton");
setScreen("verifyscreen");
}
}
}
}
}
);
return truth;
}
But nothing I do seems to get the readRecords() command working. I'm rather confused, can this asynchronous timing be meddled with at all? If not, how should I go about fixing this issue?
Thanks in advance!

using select() to detect connection close

As described in other posts, I'm trying to use select() in socket programming to detect closed connections. See the following code which tries to detect closed connections by select() and a following check on whether recv() returns 0. Before the while loop starts, there are two established TCP connections already. In our controlled experiment, the first connection always closes after about 15 seconds and the second about 30 seconds.
Theoretically (as described by others), when they get closed, select() should return (twice in our case) which allows us to detect both close events. The problem we face is that the select() now only returns once and never again, which allows us to detect ONLY the first connection close event. If the code for one IP it works fine but not for two or more connections.
Anyone has any ideas or suggestions? Thanks.
while (1)
{
printf("Waiting on select()...\n");
if ((result = select(max + 1, & readset, NULL, NULL, NULL)) < 0)
{
printf("select() failed");
break;
}
if (result > 0)
{
i=0;
while(i<max+1)
{
if (FD_ISSET(i, &readset))
{
result = recv(i, buffer, sizeof(buffer), 0);
if (result == 0)
{
close(i);
FD_CLR(i, &readset);
if (i == max)
{
max -= 1;
}
}
}
i++;
}
}
}
select() modifies readset to remove socket(s) that are not readable. Every time you call select(), you have to reset and fill readset with your latest list of active sockets that you want to test, eg:
fd_set readset;
int max;
while (1)
{
FD_ZERO(&readset);
max = -1;
// populate readset from list of active sockets...
// set max according...
printf("Waiting on select()...\n");
result = select(max + 1, &readset, NULL, NULL, NULL);
if (result < 0)
{
printf("select() failed");
break;
}
if (result == 0)
continue;
for (int i = 0; i <= max; ++i)
{
if (FD_ISSET(i, &readset))
{
result = recv(i, buffer, sizeof(buffer), 0);
if (result <= 0)
{
close(i);
// remove i from list of active sockets...
}
}
}
}

httpChannel.setRequestHeader with httpChannel.redirectTo

I'm having trouble with my Firefox-Addon.
With my extension, I'd like to redirect requests that match a certain pattern. So far, the redirection is working fine with
httpChannel.redirectTo()
Now I'd like to add / modify the request headers for the redirection (as explained here: https://developer.mozilla.org/en-US/docs/Setting_HTTP_request_headers )
My code so far:
console.log("start");
const {Cu,Ci} = require('chrome');
Cu.import('resource://gre/modules/Services.jsm');
var httpRequestObserver =
{
observe: function(subject, topic, data)
{
var httpChannel, requestURL;
if (topic == "http-on-modify-request") {
httpChannel = subject.QueryInterface(Ci.nsIHttpChannel);
requestURL = httpChannel.URI.spec;
if (requestURL.indexOf('www.3und80.de') > -1) {
console.log("match url");
newURL = 'http://www.genialschenken.de/';
/*This has no effect*/
httpChannel.setRequestHeader("X-Hello", "World", false);
console.log("redirecting...");
httpChannel.redirectTo(Services.io.newURI(newURL, null, null));
}
return;
}
}
};
Services.obs.addObserver(httpRequestObserver, "http-on-modify-request", false);
Sadly, the line
httpChannel.setRequestHeader("X-Hello", "World", false);
has no effect.
What am I doing wrong?
Thanks in advance!
From IRC:
00:58 Fallen noida: nsIChannelEventSink
00:58 Fallen and nsIInterfaceRequestor
00:59 Fallen I didn't read the link though
01:00 Fallen noida: http://mxr.mozilla.org/comm-central/source/calendar/providers/caldav/calDavCalendar.js#2828
#3und80 Let's research this more and develop an solution here.