Re: Sometimes the output to the stdout in Windows disappears - Mailing list pgsql-hackers

From Alexander Lakhin
Subject Re: Sometimes the output to the stdout in Windows disappears
Date
Msg-id b32688da-fafc-bbf6-b786-2dd7d0a4d578@gmail.com
Whole thread Raw
In response to Re: Sometimes the output to the stdout in Windows disappears  (Tom Lane <tgl@sss.pgh.pa.us>)
Responses Re: Sometimes the output to the stdout in Windows disappears
List pgsql-hackers
16.10.2020 19:18, Tom Lane wrote:
Oh, very interesting.
Now that you have it somewhat in captivity, maybe you could determine
some things:

1. Is it only stdout that's affected?  What of other stdio streams?
(Note that testing stderr might be tricky because it's probably
line-buffered.)
stderr is affected too. Just replacing stdout with stderr in connect.c and 000_connect.pl gives the same result.

Moreover, the following modification:
...
    outfile = fopen("out", "w");
...
    fprintf(stdout, "stdout test\n");
    fprintf(stderr, "stderr test\n");
    fprintf(outfile, "outfile test\n");
    WSACleanup();
...

---
for (my $i =0; $i < 100000; $i++) {
    unlink('out');
    IPC::Run::run(\@cmd, '>', \$stdout, '2>', \$stderr);
    open(my $fh, '<', 'out') or die $!;
    my $fileout = <$fh>;
    ok(defined $fileout && $fileout ne '');
    close($fh);
}

detects similar failures too. (On a fail the out file exists but has zero size.)

2. Does an fflush() just before, or just after, WSACleanup() fix it?
"fflush(NULL);" just before or after WSACleanup() fixes things.

I've managed to record in ProcMon the activity log for a failed run (aside normal runs). Excerpts from the log are attached. As we can see, the failed process doesn't even try to write into IPC-Run's temp file.

Depending on your answers to the above, maybe some hack like this
would be acceptable:
 	free(conn);  #ifdef WIN32
+	fflush(NULL); 	WSACleanup(); #endif }

It's not very nice for a library to be doing global things like that,
but if the alternative is loss of output, maybe we should.
But now we see that the WSACleanup call is a global thing by itself.
But wait a minute: I just looked at Microsoft's docs [1] and found
    In a multithreaded environment, WSACleanup terminates Windows Sockets    operations for all threads.

This makes me (a) wonder if that explains the side-effects on stdio,
and (b) question why libpq is calling WSACleanup at all.
What if we arranged to call WSAStartup just once, during the first
libpq connection-open in a process, and then never did WSACleanup?
Surely the OS can cope with that, and it eliminates any risk that
WSACleanup breaks something.
What bothers me is:
There must be a call to WSACleanup for each successful call to WSAStartup. Only the final WSACleanup function call performs the actual cleanup. The preceding calls simply decrement an internal reference count in the WS2_32.DLL.
So third-party application developers should understand that when using libpq they would have to call WSACleanup one more time to perform "the actual cleanup". (And thus WSAStartup is kind of like a global thing too.)
But may be it's a way better than to have a confirmed risk of losing data.

Best regards,
Alexander
Attachment

pgsql-hackers by date:

Previous
From: Amit Langote
Date:
Subject: Re: partition routing layering in nodeModifyTable.c
Next
From: hubert depesz lubaczewski
Date:
Subject: Re: [PATCH] Add extra statistics to explain for Nested Loop