Re: Sometimes the output to the stdout in Windows disappears

Поиск
Список
Период
Сортировка
От Alexander Lakhin
Тема Re: Sometimes the output to the stdout in Windows disappears
Дата
Msg-id b32688da-fafc-bbf6-b786-2dd7d0a4d578@gmail.com
обсуждение исходный текст
Ответ на Re: Sometimes the output to the stdout in Windows disappears  (Tom Lane <tgl@sss.pgh.pa.us>)
Ответы Re: Sometimes the output to the stdout in Windows disappears  (Tom Lane <tgl@sss.pgh.pa.us>)
Список 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
Вложения

В списке pgsql-hackers по дате отправления:

Предыдущее
От: Amit Langote
Дата:
Сообщение: Re: partition routing layering in nodeModifyTable.c
Следующее
От: hubert depesz lubaczewski
Дата:
Сообщение: Re: [PATCH] Add extra statistics to explain for Nested Loop