From: | Alexander Lakhin <exclusion(at)gmail(dot)com> |
---|---|
To: | Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us> |
Cc: | Victor Spirin <v(dot)spirin(at)postgrespro(dot)ru>, pgsql-hackers(at)lists(dot)postgresql(dot)org |
Subject: | Re: Sometimes the output to the stdout in Windows disappears |
Date: | 2020-10-17 08:00:02 |
Message-ID: | b32688da-fafc-bbf6-b786-2dd7d0a4d578@gmail.com |
Views: | Raw Message | Whole Thread | Download mbox | Resend email |
Thread: | |
Lists: | 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(\(at)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
<https://docs.microsoft.com/en-us/windows/desktop/api/winsock/nf-winsock-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 | Content-Type | Size |
---|---|---|
Logfile-OK.CSV | text/csv | 8.3 KB |
Logfile-FAIL.CSV | text/csv | 5.3 KB |
From | Date | Subject | |
---|---|---|---|
Next Message | hubert depesz lubaczewski | 2020-10-17 08:23:45 | Re: [PATCH] Add extra statistics to explain for Nested Loop |
Previous Message | Amit Langote | 2020-10-17 07:44:56 | Re: partition routing layering in nodeModifyTable.c |