#946980 parmap: segmentation fault on 32bit architectures after ocaml upgrade from 4.05.0 to 4.08.1

Package:
src:parmap
Source:
parmap
Submitter:
Johannes 'josch' Schauer
Date:
2019-12-23 16:45:03 UTC
Severity:
important
#946980#5
Date:
2019-12-18 19:52:39 UTC
From:
To:
Control: block 946817 by -1

Hi,

my package src:botch FTBFS on 32 bit architectures because of parmap:

https://buildd.debian.org/status/package.php?p=botch

the build_graph utility is run with two jobs and segfaults when the
result of the two jobs is getting joined.

I bisected snapshot.d.o to figure out where this problem comes from. The
last good snapshot timestamp is 20191102T012021Z. Then there are several
days where the build dependencies of src:botch cannot be satisfied. One
of the first timestamps where build dependencies can be satisfied again
is 20191110T012021Z eight days later. But with that timestamp, the
segfault starts happening.

At the end of this mail is the version diff of the packages that changed
between these two timestamps. Maybe something was introduced by the
ocaml upgrade that broke parmap?

Thanks!

cheers, josch

1177,1178c1177,1178
< cpp-9 9.2.1-16 i386
< cppo 1.6.6-1 i386
---
1190,1191c1190,1191
< dose-builddebcheck 5.0.1-14 i386
< dose-extra 5.0.1-14 i386
---
1194c1194
< dwz 0.13-1 i386
---
1202c1202
< g++-9 9.2.1-16 i386
---
1204,1205c1204,1205
< gcc-9 9.2.1-16 i386
< gcc-9-base 9.2.1-16 i386
---
1215c1215
< hostname 3.22 i386
---
1222,1225c1222,1225
< libasan5 9.2.1-16 i386
< libatdgen-ocaml 2.0.0-3+b1 i386
< libatdgen-ocaml-dev 2.0.0-3+b1 i386
< libatomic1 9.2.1-16 i386
---
1229,1230c1229,1230
< libbiniou-ocaml 1.2.0-1 i386
< libbiniou-ocaml-dev 1.2.0-1 i386
---
1236,1237c1236,1237
< libbz2-ocaml 0.6.0-10 i386
< libbz2-ocaml-dev 0.6.0-10 i386
---
1244,1245c1244,1245
< libcap2 1:2.25-2 i386
< libcc1-0 9.2.1-16 i386
---
1249c1249
< libcudf-ocaml-dev 0.7-5+b1 i386
---
1254,1255c1254,1255
< libdose3-ocaml 5.0.1-14 i386
< libdose3-ocaml-dev 5.0.1-14 i386
---
1257,1258c1257,1258
< libeasy-format-ocaml 1.2.0-1+b1 i386
< libeasy-format-ocaml-dev 1.2.0-1+b1 i386
---
1261,1262c1261,1262
< libextlib-ocaml 1.7.6-1 i386
< libextlib-ocaml-dev 1.7.6-1 i386
---
1266c1266
< libfindlib-ocaml 1.8.1-1 i386
---
1270,1271c1270,1271
< libgcc-9-dev 9.2.1-16 i386
< libgcc1 1:9.2.1-16 i386
---
1276c1276
< libglib2.0-0 2.62.2-2 i386
---
1278,1279c1278,1279
< libgnutls30 3.6.10-3 i386
< libgomp1 9.2.1-16 i386
---
1286c1286
< libharfbuzz0b 2.6.2-1 i386
---
1292c1292
< libitm1 9.2.1-16 i386
---
1299c1299
< liblz4-1 1.9.1-2 i386
---
1303,1304c1303,1304
< libmmap-ocaml 1.1.0-1 i386
< libmmap-ocaml-dev 1.1.0-1 i386
---
1316c1316
< libocamlgraph-ocaml-dev 1.8.8-1.1 i386
---
1325,1326c1325,1326
< libparmap-ocaml 1.0~rc10-3 i386
< libparmap-ocaml-dev 1.0~rc10-3 i386
---
1339,1340c1339,1340
< libquadmath0 9.2.1-16 i386
< libre-ocaml-dev 1.7.3-2 i386
---
1354,1355c1354,1355
< libstdc++-9-dev 9.2.1-16 i386
< libstdc++6 9.2.1-16 i386
---
1357c1357
< libsystemd0 242-7 i386
---
1361c1361
< libtiff5 4.0.10+git191003-1 i386
---
1364c1364
< libubsan1 9.2.1-16 i386
---
1366c1366
< libudev1 242-7 i386
---
1380c1380
< libxmlm-ocaml-dev 1.3.0-2 i386
---
1386,1389c1386,1389
< libyojson-ocaml 1.7.0-1 i386
< libyojson-ocaml-dev 1.7.0-1 i386
< libzip-ocaml 1.08-1 i386
< libzip-ocaml-dev 1.08-1 i386
---
1394c1394
< m4 1.4.18-2 i386
---
1402,1407c1402,1407
< ocaml-base-nox 4.05.0-12 i386
< ocaml-compiler-libs 4.05.0-12 i386
< ocaml-findlib 1.8.1-1 i386
< ocaml-interp 4.05.0-12 i386
< ocaml-nox 4.05.0-12 i386
< ocamlbuild 0.14.0-1 i386
---
1429c1429
< python3-networkx 2.2-1 all
---
1465,1466c1465,1466

#946980#8
Date:
2019-12-18 22:39:04 UTC
From:
To:
Some more details. The code using parmap is this one:

        let instsets = if num_cores > 1 then
            (* On 32 bit architectures it can happen that the result returned
             * by parmap is too big to fit into the OCaml constraints for
             * maximum allocatable memory. Should this problem occur, we
             * repeat the computation with smaller chunk sizes.
             * Unfortunately, should the result be too big and the child
             * process throws an Out_of_memory error, then all the parent
             * process sees is the Failure exception that the marshalling
             * module throws. Thus, the Failure we do catch might also be
             * caused by other problems than an Out_of_memory exception.
             * https://github.com/rdicosmo/parmap/issues/46
             *)
            let rec splitjob maxsplits todo =
              try
                Parmap.parmap ~ncores:num_cores worker (Parmap.L todo)
              with
              | Failure "input_value_from_block: bad object" -> begin
                  if maxsplits <= 0 then fatal "exceeded maximum split depth";
                  warning "parmap raised out of memory exception with list length %d, splitting job..." (List.length todo);
                  let l1, l2 = List.split_nth ((List.length todo)/2) todo in
                  let res1 = splitjob (maxsplits-1) l1 in
                  let res2 = splitjob (maxsplits-1) l2 in
                  List.append res1 res2
                end
            in
            let maxsplits = 4 in
            splitjob maxsplits todo
          else
            List.map worker todo
        in

I already had problems with parmap in the past which is why I added this
workaround for when large lists yielded an exception on 32 bit architectures.
Now, after the ocaml update, a Out_of_memory exception is thrown instead of the
Failure above but even when catching and handling that, a segfault still
happens. The segfault also happens when creating *.d.byte files.

So somewhere a behavioural change happened between 4.05.0 and 4.08.1 which
affects parmap in this way on 32 bit architectures.

Thanks!

cheers, josch

#946980#15
Date:
2019-12-23 10:26:40 UTC
From:
To:
Hi Josch,

Stéphane Glondu has uploaded biniou 1.2.1-1 on 2019-12-19, can you try
to find out whether this has solved the problem?

Cheers -Ralf.

#946980#18
Date:
2019-12-23 16:42:55 UTC
From:
To:
Hi Ralf,

Quoting Ralf Treinen (2019-12-23 11:26:40)

I find it unlikely, that biniou is the problem here. I think the problem is
this upstream bug:

https://github.com/rdicosmo/parmap/issues/46

As explained there, after replacing parmap with parany, the problem goes away.
That's why I think it's a parmap issue.

Nevertheless, I triggered a give-back:

https://buildd.debian.org/status/package.php?p=botch

As you can see, the error in the buildlog remains the same. :(

Thanks for looking into it!

cheers, josch