ghcup-hs icon indicating copy to clipboard operation
ghcup-hs copied to clipboard

Something seems wrong with ghcup installing bindist for i386 on debian 12

Open mpickering opened this issue 1 year ago • 4 comments

Something goes wrong during installation which means not all the files are copied into the installation directories.

  • https://github.com/haskell/ghcup-metadata/actions/runs/9990740016/job/27612053068

I tried in a container unpacking and manually ./configure && make install the bindist and that worked, so it appears the bindist is correct.

With the manually installed bindist I can run the tests without problems.

mpickering avatar Jul 18 '24 13:07 mpickering

Something goes wrong during installation which means not all the files are copied into the installation directories.

I don't think that's the case:

root@c3d8e90f42ba:~# file ~/.ghcup/bin/ghc
/root/.ghcup/bin/ghc: broken symbolic link to ../ghc/9.4.8/bin/ghc-9.4.8
root@c3d8e90f42ba:~# file ~/.ghcup/bin/../ghc/9.4.8/bin/ghc-9.4.8
/root/.ghcup/bin/../ghc/9.4.8/bin/ghc-9.4.8: cannot open `/root/.ghcup/bin/../ghc/9.4.8/bin/ghc-9.4.8' (Value too large for defined data type)Bourne-Again shell script, ASCII text executable
root@c3d8e90f42ba:~# ~/.ghcup/bin/../ghc/9.4.8/bin/ghc-9.4.8 --version
root@c3d8e90f42ba:~# cat ~/.ghcup/bin/../ghc/9.4.8/bin/ghc-9.4.8
#!/bin/bash
exedir="/root/.ghcup/ghc/9.4.8/lib/ghc-9.4.8/bin"
exeprog="./ghc-9.4.8"
executablename="/root/.ghcup/ghc/9.4.8/lib/ghc-9.4.8/bin/./ghc-9.4.8"
bindir="/root/.ghcup/ghc/9.4.8/bin"
libdir="/root/.ghcup/ghc/9.4.8/lib/ghc-9.4.8/lib"
docdir="/root/.ghcup/ghc/9.4.8/share/doc/ghc-9.4.8"
includedir="/root/.ghcup/ghc/9.4.8/include"

exec "$executablename" -B"$libdir" ${1+"$@"}
root@c3d8e90f42ba:~# /root/.ghcup/ghc/9.4.8/lib/ghc-9.4.8/bin/./ghc-9.4.8 --version
The Glorious Glasgow Haskell Compilation System, version 9.4.8

See that the symbolic link is considered broken, but the file is actually there. And then we get some Value too large for defined data type errors.

hasufell avatar Jul 18 '24 13:07 hasufell

I see, is there something about the way ghcup is constructing these symlinks which causes the issue? The manual bindist install seems to work correctly.

mpickering avatar Jul 18 '24 13:07 mpickering

The manual install worked locally for me but it seems something else is quite fundamentally broken on deb12 on i386. Here is a job I added to ghcup-ci testing which installs the bindist directly (and fails in a different place), which I can't reproduce locally in a docker container.

https://gitlab.haskell.org/ghc/ghcup-ci/-/jobs/1935815

mpickering avatar Jul 19 '24 11:07 mpickering

GHC issue: https://gitlab.haskell.org/ghc/ghc/-/issues/25095

mpickering avatar Jul 19 '24 14:07 mpickering

@erikd has hit this it seems

hasufell avatar Dec 02 '24 15:12 hasufell

https://github.com/haskell/ghcup-metadata/actions/runs/12122182165/job/33794792278#step:5:13728

hasufell avatar Dec 02 '24 15:12 hasufell

This was tracked down to https://github.com/haskell/unix/pull/318

Starting with the next release of GHCup, that should be fixed.

hasufell avatar Dec 22 '24 11:12 hasufell

It appears it's not fixed.

https://github.com/haskell/ghcup-metadata/actions/runs/12611467513/job/35147163425#step:5:16612

This has the good ghcup binary. I can still reproduce in a container. touch-ing the file /root/.ghcup/ghc/9.4.8/bin/ghc-9.4.8 seems to "fix" it. So there's still something wrong in unix, potentially.

hasufell avatar Jan 04 '25 15:01 hasufell

I also just ran into this. A workaround is to use ghcup 0.1.20.0, everything works for me there. All newer ghcup releases (including 0.1.40.0) produce a corrupted installation.

How to reproduce

On a x86_64-linux machine:

podman run --name ghcup-bug --arch i386 -dt i386/debian:bookworm
podman exec -it ghcup-bug bash

Then, in the container, set up some stuff:

apt update
apt install -y build-essential curl libffi-dev libffi8 libgmp-dev libgmp10 libncurses-dev libncurses5 libtinfo5
curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | BOOTSTRAP_HASKELL_NONINTERACTIVE=1 BOOTSTRAP_HASKELL_MINIMAL=1 sh
source /root/.ghcup/env
ghcup install ghc 9.6.6 --set
echo 'main = putStrLn "hi"' > test.hs

Now, try to compile test.hs:

 $ ghc test.hs
[1 of 2] Compiling Main             ( test.hs, test.o )
[2 of 2] Linking test

In file included from /tmp/ghc53990_0/ghc_3.c:1:0: error:

/root/.ghcup/ghc/9.6.6/lib/ghc-9.6.6/lib/../lib/i386-linux-ghc-9.6.6/rts-1.0.2/include/Rts.h:20:10: error:
     fatal error: /root/.ghcup/ghc/9.6.6/lib/ghc-9.6.6/lib/../lib/i386-linux-ghc-9.6.6/rts-1.0.2/include/ghcconfig.h: Value too large for defined data type
       20 | #include "ghcconfig.h"
          |          ^~~~~~~~~~~~~
   |
20 | #include "ghcconfig.h"
   |          ^
compilation terminated.

ghcup 0.1.20.0 works fine

ghcup rm ghc 9.6.6
curl -sL https://github.com/haskell/ghcup-hs/releases/download/v0.1.20.0/i386-linux-ghcup-0.1.20.0 > /root/.ghcup/bin/ghcup
chmod +x /root/.ghcup/bin/ghcup
ghcup install ghc 9.6.6 --set
ghc test.hs && ./test

amesgen avatar Jan 31 '25 23:01 amesgen

Yes, I thought for a moment that it's a bug in unix.

After an installation with i386 ghcup:

ghci> t <- getModificationTime "/root/.ghcup/ghc/9.4.8/bin/ghc-9.4.8"
ghci> t
2038-01-19 03:14:07 UTC
ghci> utcTimeToPOSIXSeconds t
2147483647s
ghci> maxBound :: Int
2147483647

It appears the max bound is causing issues with musl. But the question is how did it end up messed up that way in the first place.

I could not reproduce the issue with setModificationTime etc. on debian 12 in ghci manually, nor when I build ghcup there. This suggests there must be an issue with a combination of musl version and linux kernel version?

hasufell avatar Feb 01 '25 09:02 hasufell

Hi @hasufell, I found this issue from here. My guess is this is caused because the musl library the builder is using has transitioned to time64, but the GHC the builder is using is not.

Background

In order to solve the Y2038, libc and musl migrated to a 64-bit size for time_t. You can find more information here and here. The gist is that this is an ABI breaking change, and binaries that link against versions of libc/musl that use time64 need to be recompiled.

The issue

  1. The image we are using to build the i386 package for ghcup has musl with time64.

    You can verify this by running the following:

    $ docker run -ti --rm hasufell/i386-alpine-haskell:3.21 /bin/bash
    632b1225802d:/# echo -e '#include <stdio.h>\n#include <time.h>\nvoid main() { printf("%u\\n", sizeof(time_t)); }' > foo.c
    632b1225802d:/# gcc -o foo foo.c
    632b1225802d:/# ./foo
    8
    
  2. The GHC we are using considers time_t to be 32-bit.

    This happens either because this GHC was not compiled with 64-bit time_t, or because this GHC is old and doesn't contain the necessary fixes to support time64 (e.g., https://gitlab.haskell.org/ghc/packages/time/-/commit/d52314edb138b6ecd7e888c588f83917b0ee2c29, https://gitlab.haskell.org/ghc/packages/directory/-/commit/f6b288bd96fba5a955d1f73663eb52c1859ee765 etc). You can verify this is the case with the following:

    $ docker run -ti --rm hasufell/i386-alpine-haskell:3.21 /bin/bash
    ... (Download and install https://downloads.haskell.org/~ghcup/unofficial-bindists/ghc/8.10.7/ghc-8.10.7-i386-alpine-linux.tar.xz)
    ghci> import Foreign.Storable
    ghci> import Foreign.C.Types
    ghci> sizeOf (0 :: CTime)
    4
    
  3. Since musl and GHC disagree about the size of CTime, this means that GHC itself may misbehave, and also that any programs that are compiled with this GHC will be broken wrt time operations. This is why the ghcup binary doesn't work.

Solution

You can try with a newer GHC (e.g., https://downloads.haskell.org/~ghcup/unofficial-bindists/ghc/9.6.7/ghc-9.6.7-i386-linux-alpine-3.17.7.tar.xz) which seems to be properly compiled for musl with time64.

iliastsi avatar Apr 01 '25 21:04 iliastsi

i386 alpine built with 9.6.7 seems to segfault: https://github.com/haskell/ghcup-hs/actions/runs/14350951698/job/40230400883?pr=1252#step:6:546

hasufell avatar Apr 09 '25 07:04 hasufell