We help IT Professionals succeed at work.

Check out our new AWS podcast with Certified Expert, Phil Phillips! Listen to "How to Execute a Seamless AWS Migration" on EE or on your favorite podcast platform. Listen Now

x

select and WaitForMultipleObjects

meessen
meessen asked
on
Medium Priority
2,768 Views
Last Modified: 2013-12-03
Hello,

I'm writing a small program that needs to wait on socket I/O and on process I/O using pipes.

To detect pipe I/O I must use WaitForMultipleObjects and for socket I/O I must use select.
These waits are incompatible. I can't even interrupt one if there is data to forward bewteen them.
Is there a way to use select or WaitForMultipleObjects to wait for all types of event without needing to poll ?

Do I have to go for threads where I could avoid it in unix ?


Comment
Watch Question

Commented:
Unlock this solution and get a sample of our free trial.
(No credit card required)
UNLOCK SOLUTION

Author

Commented:
The good news is that I use Windows socket implementation.

I created a listening socket and passed it to WaitFor MultipleObjects but apparently the object doesn't become signaled when a connection is done. So I stay with a pending connection. This might be THE exception.

It would be great if I could wait for incomming connections,socket I/O, child processes death and child process I/o through pipe in a single call.

Unfortunately the incomming connection did never signaled the object so I did not test the rest. It's useless unless you can confirm to me that it should work and the problem might be in my code.

Beside I need to port this beast on unix.

Author

Commented:
The good news is that I use Windows socket implementation.

I created a listening socket and passed it to WaitFor MultipleObjects but apparently the object doesn't become signaled when a connection is done. So I stay with a pending connection. This might be THE exception.

It would be great if I could wait for incomming connections,socket I/O, child processes death and child process I/o through pipe in a single call.

Unfortunately the incomming connection did never signaled the object so I did not test the rest. It's useless unless you can confirm to me that it should work and the problem might be in my code.

Beside I need to port this beast on unix.

Author

Commented:
I checked again for WaitFor... with a listening socket and it doesn't work. It works well with select.

Select signals an error when given a Process handle or a pipe handle. This behaves as documented.

And the answer is .....

WSAEventSelect !

This makes my code portable ! Great !


Author

Commented:
Well of course WSAEventSelect is documented but is not provided in the library and most probably not implemented. Thank you M$...

Any other idea ?

Author

Commented:
Now suppose I want to use two threads. select is used for socket io thread.
And WaitFor... in a child process listening thread.
I could use event objects to unblock a WaitFor when network data has come in.
But how do I unblock a select ?

This means that the WaitFor... must do the socket send using non blocking calls.

Excuuuse me be this is getting really twisted for what look like a very simple and academic application. And we can definitively forget about protability here.

I'm desperate... and this work is soo urgent as usual !

Commented:
If you want portable code, have you considered using ACE?  It is a library that encapsulates a lot of multiprocessing and communications concepts, and is quite extensive.  Check out http://www.cs.wustl.edu/~schmidt

It might be your best bet to get this thing running on both platforms....

Author

Commented:
I know ACE but I don't have time and the experience to use this package.

I now have a input thread imlementing the select operation for new connection and incomming data on sockets. I use event to signal incomming data.

I have a main thread using WaitFor... and it works fine. Well nearly fine.

The problem left is that when I start the process using pipes to redirect I/O I check the child process output pipe if it is signaled. Apparently it is but When I try to ReadFile on it the call blocks. And of course everything blocks since I never go back to the WaitFor and give other task a chance  to be executed.

Any clue on what could make this ReadFile block ?

I have a buffer of size BUFSIZE.
I do ReadFile( proc->stdout, buffer, BUFSIZE, &len, NULL );


If I manualy kill the child process, the pipe is released, and the read is terminated.
I know the process is sending an output line.

What I don't understand is why the output pipe handle is signaled and a ReadFIle will block !


Author

Commented:
Even worse....

I have written a small dummy program doing the following:
int main( int argc, char* argv[] ){
      HANDLE so;
      long len;
      char msg[] = "+ Hello\n";

      for( ;; ){
            int i;
            printf("- hello\r\n");

            so = GetStdHandle(STD_OUTPUT_HANDLE);
            WriteFile( so, msg, strlen(msg), &len, NULL );
            for( i = 1; i < 50000; i++ )
                  i = (i*2)/2;
      }
      return 0;
}

When run from the console I get
+ Hello
- hello
+ Hello
- hello
+ Hello
- hello
+ Hello
- hello
+ Hello
- hello
as expected.

Now run as a child process and doing a synchronous ReadFile on the stdout handle I get
A big bunch of + Hello and suddently a big bunch of - hello.
I didn't check but I guess the number of output lines is the same.
Very usefull feature.

We are now going to evaluate Linux and solaris on Intel for our 3.5 Million Dollar project.





Commented:
Problem one: ReadFile doesn't return until the piped task terminates.
This is a direct result of what ReadFile is doing: Reading data until EOF.  You don't get an EOF on stdin until the process that is piping to you terminates, or the buffer is exceeded.  What I think you want to do is to read in data in smaller chunks (a byte at a time, maybe?) and process it as you see it.  You might also want to consider overlapped I/O, so you can properly handle time-outs on the input....

Problem two: Unsynchronized I/O
I think you need to flush stdin/stdout to get the two streams synchronized.  Try this:
int main( int argc, char* argv[] ){
    HANDLE so;
    long len;
    char msg[] = "+ Hello\n";

    for( ;; ){
        int i;
        printf("- hello\r\n");
        fflush( stdout);

        so = GetStdHandle(STD_OUTPUT_HANDLE);
        WriteFile( so, msg, strlen(msg), &len, NULL );
        FlushFileBuffers( so);
        for( i = 1; i < 50000; i++ )
            i = (i*2)/2;
    }
    return 0;
}


Unlock the solution to this question.
Thanks for using Experts Exchange.

Please provide your email to receive a sample view!

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

OR

Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.