0

I have a cross-platform (Windows 8/OSX 10.10) test application which, as part of the test, needs to spawn a child process which will listen on a port (can be dynamic or specified). The child process (call it MockServer), upon startup, will send to stdout a line that looks like:

Server listening on localhost:50015

In the code that spawns the mock server, I'm doing this:

//  globals
QProcess ServerMockProcess;
QString ServerPort

void
startServerMock()
{
    ServerMockProcess.start(SERVER_MOCK_EXE);
    ServerMockProcess.waitForReadyRead(2000);
    char buf[1024];
    qint64 lineLength = ServerMockProcess.readLine(buf, sizeof(buf));
    QString output;
    int port = 0;
    if (lineLength != -1) {
        output = buf;
        std::cout << output << std::endl;

        // A successful startup will produce output that looks like:
        // Server listening on localhost:50015
        ServerPort = output.section(":", -1);
        ServerPort.chop(1); // remove newline
        port = ServerPort.toInt();
    }

    if (!port) {
        QString msg = "Couldn't start " SERVER_MOCK_EXE ": " + output;
        std::cerr << msg << std::endl;
        throw FILESYSTEM_EXCEPTION(msg);
    }
    std::cout << "Talking to " << ServerPort << std::endl;
}

On both platforms, the code above appears to work - I see a two lines appear when this function is called, e.g.:

Server listening on 127.0.0.1:53869

Talking to 53869

Subsequently, I invoke code that will cause the test application to talk to the server application (using GRPC, in this case). The SERVER_MOCK_EXE can take a command line argument specifying a port, or if left blank, it dynamically chooses one (with the stdout advertising the port). On OSX, this code works correctly. However, on Windows, attempting to open a GRPC connection results in these errors:

E0922 07:43:07.436000000  6420 resolve_address_windows.c:99] getaddrinfo: The specified class was not found.

D0922 07:43:07.436000000  6420 dns_resolver.c:186] dns resolution failed: retrying in 1.000000000 seconds
E0922 07:43:08.440000000  5296 resolve_address_windows.c:99] getaddrinfo: The specified class was not found.

D0922 07:43:08.441000000  5296 dns_resolver.c:186] dns resolution failed: retrying in 1.773000000 seconds
E0922 07:43:10.218000000  1752 resolve_address_windows.c:99] getaddrinfo: The specified class was not found.

D0922 07:43:10.219000000  1752 dns_resolver.c:186] dns resolution failed: retrying in 2.841000000 seconds

After much experimentation, I discovered that what was breaking the server was the reading of stdout to get the port. If I instead hard-coded a port and passed it in, the server process could be communicated with:

void
startServerMock()
{
    ServerMockProcess.start(SERVER_MOCK_EXE " 53869");
    ServerMockProcess.waitForReadyRead(2000);
    ServerPort = "53869";
    std::cout << "Talking to " << ServerPort << std::endl;
}

It isn't just the dynamic port allocation that is breaking it, since invoking the first version of the function with the line

    ServerMockProcess.start(SERVER_MOCK_EXE " 53869");

instead of leaving it blank still results in the networking errors above.

Any ideas?

Steve Broberg
  • 4,255
  • 3
  • 28
  • 40
  • Where is `sessionServerPort` defined? – SingerOfTheFall Sep 22 '16 at 14:56
  • In those cases where you see the failure what is the value of the `QString` variable `output`? You're code makes some fairly strict assumptions about what the output of `SERVER_MOCK_EXE` will look like. – G.M. Sep 22 '16 at 15:12
  • `QProcess`' I/O redirection code (on Windows) is broken beyond hope of regeneration. Don't use. – IInspectable Sep 22 '16 at 15:45
  • @SingerOfTheFall: Fixed the definition of some globals for clarity – Steve Broberg Sep 22 '16 at 16:22
  • @G.M.: In the cases of failure, the value of output (and the messages sent to stdout) look exactly the same as when it is successful (at least, successful on OSX) - the line stating "Server listening on 127.0.0.1:XXXX" followed by "Talking to XXXX". The server is written by us, so anything other than that output is considered a failure to start correctly. – Steve Broberg Sep 22 '16 at 16:24

0 Answers0