msys2 / MINGW-packages

Package scripts for MinGW-w64 targets to build under MSYS2.
https://packages.msys2.org
BSD 3-Clause "New" or "Revised" License
2.3k stars 1.22k forks source link

fopen(pipe, "wb") fails in msys2 but succeeds in Visual Studio #5903

Closed desowin closed 5 years ago

desowin commented 5 years ago

Consider following code:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <time.h>
#include <Windows.h>

int main()
{
    HANDLE hpipe;
    char pipename[MAX_PATH];
    char timestr[14 + 1];
    time_t current_time;
    SECURITY_ATTRIBUTES security;
    FILE* client;

    current_time = time(NULL);
    strftime(timestr, sizeof(timestr), "%Y%m%d%H%M%S", localtime(&current_time));
    snprintf(pipename, sizeof(pipename), "\\\\.\\pipe\\msys_example_%s", timestr);

    memset(&security, 0, sizeof(SECURITY_ATTRIBUTES));
    security.nLength = sizeof(SECURITY_ATTRIBUTES);
    security.bInheritHandle = TRUE;
    security.lpSecurityDescriptor = NULL;

    hpipe = CreateNamedPipeA(pipename, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
        PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
        1, 65536, 65536, 300, &security);

    if (hpipe == INVALID_HANDLE_VALUE)
    {
        fprintf(stderr, "Failed to create named pipe\n");
        return 1;
    }

    client = fopen(pipename, "wb");
    if (client)
    {
        fprintf(stdout, "Successfully connected to pipe\n");
        fclose(client);
    }
    else
    {
        fprintf(stderr, "Failed to connect to pipe\n");
    }

    CloseHandle(hpipe);
    return 0;
}

When compiled with Visual Studio (eg. Community 2019), the executable prints out:

Successfully connected to pipe

When compiled with gcc in msys2, the executable prints out:

Failed to connect to pipe

I would expect the code to work the same with msys2 as it does in Visual Studio.

Alexpux commented 5 years ago

@desowin, first verify that you build with mingw GCC, not msys GCC. If it is true then better to bugreport to mingw-w64 mailing list

desowin commented 5 years ago

@desowin, first verify that you build with mingw GCC, not msys GCC. If it is true then better to bugreport to mingw-w64 mailing list

I am not sure what you mean. The binary fails if it uses msys-2.0.dll.

desow@desowin-laptop MINGW32 ~
$ gcc /c/Development/pipe.c -o pipe.exe

desow@desowin-laptop MINGW32 ~
$ ldd pipe.exe
        ntdll.dll => /c/WINDOWS/SYSTEM32/ntdll.dll (0x7ffd8ab00000)
        KERNEL32.DLL => /c/WINDOWS/System32/KERNEL32.DLL (0x7ffd8a290000)
        KERNELBASE.dll => /c/WINDOWS/System32/KERNELBASE.dll (0x7ffd88760000)
        msys-2.0.dll => /usr/bin/msys-2.0.dll (0x180040000)

desow@desowin-laptop MINGW32 ~
$ ./pipe.exe
Failed to connect to pipe

while compiling the same file with gcc installed via mingw-get works:

desow@desowin-laptop MINGW32 /c/MinGW/bin
$ ./gcc /c/Development/pipe.c -o pipe-mingw.exe

desow@desowin-laptop MINGW32 /c/MinGW/bin
$ ldd pipe-mingw.exe
        ntdll.dll => /c/WINDOWS/SYSTEM32/ntdll.dll (0x7ffd8ab00000)
        ??? => ??? (0x77740000)
        wow64.dll => /c/WINDOWS/System32/wow64.dll (0x7ffd895d0000)
        wow64win.dll => /c/WINDOWS/System32/wow64win.dll (0x7ffd89fa0000)

desow@desowin-laptop MINGW32 /c/MinGW/bin
$ ./pipe-mingw.exe
Successfully connected to pipe
desowin commented 5 years ago
desow@desowin-laptop MSYS ~
$ gcc /c/Development/pipe.c -o pipe-msys.exe

desow@desowin-laptop MSYS ~
$ ldd pipe-msys.exe
        ntdll.dll => /c/WINDOWS/SYSTEM32/ntdll.dll (0x7ffd8ab00000)
        KERNEL32.DLL => /c/WINDOWS/System32/KERNEL32.DLL (0x7ffd8a290000)
        KERNELBASE.dll => /c/WINDOWS/System32/KERNELBASE.dll (0x7ffd88760000)
        msys-2.0.dll => /usr/bin/msys-2.0.dll (0x180040000)

desow@desowin-laptop MSYS ~
$ ./pipe-msys.exe
Failed to connect to pipe
Alexpux commented 5 years ago

@desowin you use Msys GCC, it is like Cygwin GCC. So use proper GCc

desowin commented 5 years ago

@desowin you use Msys GCC, it is like Cygwin GCC. So use proper GCc

I am sorry, but I still don't understand. I believe the issue is not with gcc but rather with the standard library implementation. When compiled with cygwin:

desow@desowin-laptop ~
$ gcc /cygdrive/c/Development/pipe.c -o pipe-cygwin.exe                                                                 
desow@desowin-laptop ~
$ ldd pipe-cygwin.exe
        ntdll.dll => /cygdrive/c/WINDOWS/SYSTEM32/ntdll.dll (0x7ffd8ab00000)
        KERNEL32.DLL => /cygdrive/c/WINDOWS/System32/KERNEL32.DLL (0x7ffd8a290000)
        KERNELBASE.dll => /cygdrive/c/WINDOWS/System32/KERNELBASE.dll (0x7ffd88760000)
        cygwin1.dll => /usr/bin/cygwin1.dll (0x180040000)

desow@desowin-laptop ~
$ ./pipe-cygwin.exe
Failed to connect to pipe

The issue seems to be connected with the fopen() implementation that is in both msys-2.0.dll and in cygwin1.dll. The libraries used by mingw-get package are not affected. I am not sure where is the actual source code that is used to build msys-2.0.dll.

StarWolf3000 commented 5 years ago

Just use MINGW GCC (/mingw32/bin/gcc.exe / /mingw64/bin/gcc.exe), and not MSYS2 GCC (/usr/bin/gcc.exe).

MINGW GCC is for native applications, like Visual Studio outputs, that don't use a POSIX layer/are not POSIX compliant. MSYS2 GCC is for utilities and the MSYS2 environment, and produces binaries that are POSIX compliant and are similar to Cygwin.

But this is strange:

desow@desowin-laptop MINGW32 ~
$ gcc /c/Development/pipe.c -o pipe.exe

desow@desowin-laptop MINGW32 ~
$ ldd pipe.exe
        ntdll.dll => /c/WINDOWS/SYSTEM32/ntdll.dll (0x7ffd8ab00000)
        KERNEL32.DLL => /c/WINDOWS/System32/KERNEL32.DLL (0x7ffd8a290000)
        KERNELBASE.dll => /c/WINDOWS/System32/KERNELBASE.dll (0x7ffd88760000)
        msys-2.0.dll => /usr/bin/msys-2.0.dll (0x180040000)

desow@desowin-laptop MINGW32 ~
$ ./pipe.exe
Failed to connect to pipe

GCC under MINGW(32/64) environment should not link against msys-2.0.dll. It should link to msvcrt.dll. Did you somehow mess up with your installation?

desowin commented 5 years ago

GCC under MINGW(32/64) environment should not link against msys-2.0.dll. It should link to msvcrt.dll. Did you somehow mess up with your installation?

Depending what you mean by mess up with the installation. I only did pacman -Syuu and then pacman -Syu gcc. I didn't have /mingw32/bin/gcc.exe nor /mingw64/bin/gcc.exe.

I have run pacman -Syu mingw-w64-i686-gcc and pacman -Syu mingw-w64-x86_64-gcc and now both in the MINGW32 and MINGW64 environments the which gcc returns respectively /mingw32/bin/gcc or /mingw64/bin/gcc. Both /mingw32/bin/gcc and /mingw64/bin/gcc produces working binary with the example code (linked against msvcrt.dll).

Am I understanding it correctly that msys-2.0.dll fopen() is not supposed to be able to open Windows pipes?

StarWolf3000 commented 5 years ago

Depending what you mean by mess up with the installation. I only did pacman -Syuu and then pacman -Syu gcc. I didn't have /mingw32/bin/gcc.exe nor /mingw64/bin/gcc.exe.

I have run pacman -Syu mingw-w64-i686-gcc and pacman -Syu mingw-w64-x86_64-gcc and now both in the MINGW32 and MINGW64 environments the which gcc returns respectively /mingw32/bin/gcc or /mingw64/bin/gcc. Both /mingw32/bin/gcc and /mingw64/bin/gcc produces working binary with the example code (linked against msvcrt.dll).

Ah, so you actually didn't have the actual compilers installed, so calling gcc fell back to MSYS2.

As for your question regarding fopen() and Windows pipes on a Cygwin environment (which basically MSYS2 is), I think the problem is the actual path is not valid in the sense of POSIX. Also I don't think Cygwin does currently support named pipes on Windows. See also vifm/vifm#189

oscarfv commented 5 years ago

@desowin : Since the confusion is cleared, please close the bug report. Thanks.

Unless you plan to build MSYS2-based executables, removing the packages gcc and its dependencieswill avoid the same mistake on the future:

pacman -Rs gcc