Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix and enforce reinterpret/unsafe_wrap alignment #21831

Merged
merged 2 commits into from
May 18, 2017
Merged

Fix and enforce reinterpret/unsafe_wrap alignment #21831

merged 2 commits into from
May 18, 2017

Conversation

yuyichao
Copy link
Contributor

The first commit is a bug fix that fixes a LLVM undefined behavior which actually cause segfault on ARM and is the one that should be backported. The second commit is to reflect this semantic requirement in the julia API so that we won't have this kind of bug in the future especially since we've actually had this kind of bug in the test before...

It is in principle possible to loosen the alignment check in reinterpret on the pointer though that make this kind of bug much harder to catch/reason about. We should ideally also run PkgEval on it to identify buggy packages.

@yuyichao yuyichao added system:arm ARMv7 and AArch64 backport pending 0.6 breaking This change will break code labels May 12, 2017
@yuyichao
Copy link
Contributor Author

@jlbuild !filter=arm,aarch64,ppc64

@jlbuild
Copy link

jlbuild commented May 12, 2017

Status of 2c57766 builds:

Builder Name Build Download
linuxaarch64 COMPLETE Download
linuxarmv7l ERRORED N/A
linuxppc64le COMPLETE Download

@yuyichao
Copy link
Contributor Author

@nanosoldier runbenchmarks(ALL, vs=":master")

base/bitarray.jl Outdated
%p = getelementptr i64, i64* %0, i64 %1
%v = load i64, i64* %p, align 1
ret i64 %v
""", UInt64, Tuple{Ptr{UInt64},Int64}, p64, Int64(idx - 1))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return Core.Intrinsics.pointerref(p64, #=1 based=# idx, #=align (constant)=# 1)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and then can call this unsafe_load_unaligned, and just define it the same as unsafe_load

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure. I was actually going to just call it inline....

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually I didn't realize that unsafe_load uses align 1 so I'll just use that......................

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah right – I forgot that I originally didn't trust users / C libraries to declare types exactly correct :P (and then the align attribute was added because the GPU folks complained that it was being too pessimistic)

@yuyichao yuyichao force-pushed the yyc/align branch 2 times, most recently from a78c5fc to 5819ae1 Compare May 12, 2017 19:44
@nanosoldier
Copy link
Collaborator

Your benchmark job has completed - possible performance regressions were detected. A full report can be found here. cc @jrevels

src/array.c Outdated
}
if (((uintptr_t)data) & (align - 1))
jl_exceptionf(jl_argumenterror_type,
"unsafe_wrap: pointer %p is not properly aligned to %u", data, align);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

aligned to %u bytes?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would be clearer imo (and in the other instance below)

@@ -4848,12 +4856,15 @@ end
let ni128 = sizeof(FP128test) ÷ sizeof(Int),
ns128 = sizeof(FP128align) ÷ sizeof(Int),
nbit = sizeof(Int) * 8,
arr = reinterpret(FP128align, collect(Int, 1:(2 * ns128))),
arr = Vector{FP128align}(2),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this be larger than 2 on 32 bit?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No. The original size is 2 * ns128 * sizeof(Int) ÷ sizeof(FP128align) == 2 * sizeof(FP128align) ÷ sizeof(Int) * sizeof(Int) ÷ sizeof(FP128align) == 2

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

makes sense – we want to allocate this with the larger alignment (FP128align), but fill it with the smaller alignment (Int)

@staticfloat
Copy link
Member

EOFError()CapturedException(EOFError(), Any[(unsafe_read(::Base.AbstractIOBuffer{Array{UInt8,1}}, ::Ptr{UInt8}, ::UInt32) at iobuffer.jl:105, 1), (unsafe_read(::TCPSocket, ::Ptr{UInt8}, ::UInt32) at stream.jl:752, 1), (unsafe_read(::TCPSocket, ::Base.RefValue{NTuple{4,Int32}}, ::Int32) at io.jl:361, 1), (read at io.jl:363 [inlined], 1), (deserialize_hdr_raw at messages.jl:170 [inlined], 1), (message_handler_loop(::TCPSocket, ::TCPSocket, ::Bool) at process_messages.jl:157, 1), (process_tcp_streams(::TCPSocket, ::TCPSocket, ::Bool) at process_messages.jl:118, 1), ((::Base.Distributed.##99#100{TCPSocket,TCPSocket,Bool})() at event.jl:73, 1)])

Welp, at least we get an exciting new error now...

@yuyichao
Copy link
Contributor Author

Any comment? (This got significantly fewer comments than I expected).

Also what's the most up to date method of running PkgEval?

@tkelman
Copy link
Contributor

tkelman commented May 15, 2017

It's kind of hacky and manual at the moment. I don't have a branch for nightly = 0.7 yet, but https://github.com/JuliaCI/PackageEvaluator.jl/tree/backport-0.6.0-rc2 is what I used for rc2 - change the parts of setup.sh that set the binary to download and the metadata subset to run on, trigger a linux 64 packaging run and use that binary for "LZ" (the vm names are lies when running this kind of comparison)

@yuyichao
Copy link
Contributor Author

I assume the binary from the buil 🐶 can also be used for this?

@jlbuild !filter=arm,aarch64,ppc64,linux64

@jlbuild
Copy link

jlbuild commented May 15, 2017

Status of 38aa2ce builds:

Builder Name Build Download
linux64 ERRORED N/A
linuxaarch64 CANCELED N/A
linuxarmv7l CANCELED N/A
linuxppc64le ERRORED N/A

@yuyichao
Copy link
Contributor Author

Updated the error message without updating the test.... Try again..................

@jlbuild !filter=arm,aarch64,ppc64,linux64

@jlbuild
Copy link

jlbuild commented May 16, 2017

Status of 4bd5f81 builds:

Builder Name Build Download
linux64 COMPLETE Download
linuxaarch64 COMPLETE Download
linuxarmv7l ERRORED N/A
linuxppc64le COMPLETE Download

@yuyichao
Copy link
Contributor Author

The fault on ARM doesn't even make sense

GDB shows a ldrh r8, [r0, r2] instruction loading a properly aligned and accessible address while still segfaulted.....

dmesg log when the segv handler is removed.

[6744582.780698] pgd = ffff80022e103000
[6744582.784271] [f6bf92ec] *pgd=00000087c0bba003, *pud=00000081b79a9003, *pmd=00000084bb578003, *pte=0000000000000000

[6744582.794724] CPU: 2 PID: 18383 Comm: julia-debug Tainted: G        W I     4.10.1-1-ARCH #1
[6744582.794726] Hardware name: AMD Overdrive/Supercharger/To be filled by O.E.M., BIOS ROD1002C 04/08/2016
[6744582.794728] task: ffff800505db0080 task.stack: ffff800151cb0000
[6744582.794730] PC is at 0xf5c013a4
[6744582.794732] LR is at 0x18
[6744582.794734] pc : [<00000000f5c013a4>] lr : [<0000000000000018>] pstate: a0000010
[6744582.794735] sp : 00000000ffbf54a0
[6744582.794736] x12: 00000000f6bb7bca
[6744582.794738] x11: 000000000095cb88 x10: 000000000176145c
[6744582.794741] x9 : 00000000f6bb7bca x8 : 0000000000000001
[6744582.794744] x7 : 000000000000fd9c x6 : 0000000000000000
[6744582.794747] x5 : 0000000000000000 x4 : 00000000f6bf92ec
[6744582.794749] x3 : 00000000f6bb7bc8 x2 : 000000000003f670
[6744582.794751] x1 : 00000000f6bb4a50 x0 : 00000000f6bb9c7c

@yuyichao
Copy link
Contributor Author

@jlbuild !filter=arm !nuke

@jlbuild
Copy link

jlbuild commented May 16, 2017

Status of 4bd5f81 builds:

Builder Name Nuke Build Download
linuxarmv7l COMPLETE ERRORED N/A

@yuyichao
Copy link
Contributor Author

PkgEval results below.

I've only check LegacyStrings and it's a legit bug. I'll check more packages later but I don't expect this to cause any false positives.

The new ARM failure on buidog is #21926

--- master      2017-05-17 11:42:40.483749791 -0400
+++ pr  2017-05-17 11:42:48.443905204 -0400
@@ -60,7 +60,7 @@
 BaseTestNext.json "tests_fail"
 BasisMatrices.json "tests_pass"
 BayesianDataFusion.json "tests_fail"
-BayesianNonparametrics.json "tests_pass"
+BayesianNonparametrics.json "tests_fail"
 BayesNets.json "tests_fail"
 BDF.json "tests_pass"
 BeaData.json "tests_pass"
@@ -87,7 +87,7 @@
 Blocks.json "tests_fail"
 BloomFilters.json "tests_pass"
 Blosc.json "tests_pass"
-BlossomV.json "tests_pass"
+BlossomV.json "tests_fail"
 BlsData.json "tests_fail"
 Bokeh.json "tests_fail"
 Boltzmann.json "tests_fail"
@@ -142,7 +142,7 @@
 ClusterUtils.json "tests_fail"
 CMakeWrapper.json "tests_pass"
 COBRA.json "tests_fail"
-Codecs.json "tests_pass"
+Codecs.json "tests_fail"
 CodeTools.json "tests_pass"
 COESA.json "tests_pass"
 COFF.json "tests_fail"
@@ -198,7 +198,7 @@
 CPUTime.json "tests_pass"
 CQL.json "tests_fail"
 Crayons.json "tests_pass"
-CRC.json "tests_pass"
+CRC.json "tests_fail"
 CreateMacrosFrom.json "tests_pass"
 CRF.json "tests_fail"
 CRlibm.json "tests_pass"
@@ -227,7 +227,7 @@
 CUTEst.json "tests_fail"
 CutPruners.json "tests_pass"
 CVXOPT.json "tests_pass"
-Cxx.json "tests_pass"
+Cxx.json "tests_fail"
 CxxWrap.json "tests_pass"
 Dagger.json "tests_pass"
 DASKR.json "tests_pass"
@@ -344,7 +344,7 @@
 EnhancedGJK.json "tests_fail"
 Ensemble.json "tests_fail"
 Equations.json "tests_fail"
-Erdos.json "tests_pass"
+Erdos.json "tests_fail"
 ERFA.json "tests_pass"
 ErrorfreeArithmetic.json "tests_pass"
 Escher.json "tests_fail"
@@ -521,10 +521,10 @@
 IJulia.json "not_possible"
 IJuliaPortrayals.json "tests_fail"
 ImageAxes.json "tests_pass"
-ImageCore.json "tests_pass"
+ImageCore.json "tests_fail"
 ImageFiltering.json "tests_pass"
 ImageInTerminal.json "tests_fail"
-ImageMagick.json "tests_pass"
+ImageMagick.json "tests_fail"
 ImageMetadata.json "tests_pass"
 ImageProjectiveGeometry.json "tests_pass"
 ImageQuilting.json "tests_pass"
@@ -556,7 +556,7 @@
 Interact.json "tests_pass"
 InterestRates.json "tests_pass"
 Interfaces.json "tests_fail"
-Interpolations.json "tests_fail"
+Interpolations.json "tests_pass"
 IntervalArithmetic.json "tests_pass"
 IntervalConstraintProgramming.json "tests_pass"
 IntervalContractors.json "tests_pass"
@@ -588,7 +588,7 @@
 JLDArchives.json "tests_fail"
 JLD.json "tests_fail"
 JointMoments.json "tests_fail"
-JPLEphemeris.json "tests_pass"
+JPLEphemeris.json "tests_fail"
 JSON.json "tests_pass"
 JuliaFEM.json "tests_fail"
 JuliaParser.json "tests_fail"
@@ -631,7 +631,7 @@
 LearnBase.json "tests_pass"
 LearningStrategies.json "tests_pass"
 LeastSquaresOptim.json "tests_fail"
-LegacyStrings.json "tests_pass"
+LegacyStrings.json "tests_fail"
 Lens.json "tests_fail"
 LevelDB.json "tests_fail"
 Levenshtein.json "tests_fail"
@@ -710,7 +710,7 @@
 MatrixNetworks.json "tests_pass"
 Maxima.json "tests_fail"
 Mayday.json "tests_pass"
-MbedTLS.json "tests_pass"
+MbedTLS.json "tests_fail"
 MCMC.json "no_tests"
 MDCT.json "tests_pass"
 MDPs.json "tests_fail"
@@ -810,7 +810,7 @@
 NonNegLeastSquares.json "tests_pass"
 NormalizeQuantiles.json "tests_pass"
 NoveltyColors.json "tests_pass"
-NPZ.json "tests_pass"
+NPZ.json "tests_fail"
 NRRD.json "tests_fail"
 NullableArrays.json "tests_pass"
 NumberedLines.json "tests_pass"
@@ -837,7 +837,7 @@
 OnlineStats.json "tests_pass"
 OpenCL.json "not_possible"
 OpenDSSDirect.json "tests_pass"
-OpenEphysLoader.json "tests_pass"
+OpenEphysLoader.json "tests_fail"
 OpenFOAM.json "tests_fail"
 OpenGene.json "tests_fail"
 OpenStreetMap.json "tests_fail"
@@ -871,7 +871,7 @@
 PathDistribution.json "tests_pass"
 PATHSolver.json "tests_pass"
 PatternDispatch.json "tests_fail"
-Pcap.json "tests_pass"
+Pcap.json "tests_fail"
 PdbTool.json "tests_fail"
 PDMats.json "tests_pass"
 Pedigrees.json "tests_fail"
@@ -1075,7 +1075,7 @@
 SFML.json "tests_fail"
 SGDOptim.json "tests_fail"
 SGP4.json "tests_pass"
-SHA.json "tests_pass"
+SHA.json "tests_fail"
 Shannon.json "tests_fail"
 Shapefile.json "tests_pass"
 ShapeModels.json "tests_fail"
@@ -1146,7 +1146,7 @@
 StokesDiffEq.json "tests_pass"
 StreamStats.json "tests_fail"
 StringDistances.json "tests_pass"
-StringEncodings.json "tests_pass"
+StringEncodings.json "tests_fail"
 StringInterpolation.json "tests_pass"
 StrPack.json "tests_fail"
 StructIO.json "tests_fail"
@@ -1260,7 +1260,7 @@
 VisualRegressionTests.json "tests_pass"
 VLFeat.json "tests_fail"
 VML.json "not_possible"
-VoronoiCells.json "tests_pass"
+VoronoiCells.json "tests_fail"
 VoronoiDelaunay.json "tests_pass"
 Voronoi.json "tests_pass"
 Voting.json "tests_fail"
@@ -1292,7 +1292,7 @@
 WordNet.json "tests_pass"
 WorldBankData.json "tests_fail"
 WORLD.json "tests_pass"
-WriteVTK.json "tests_pass"
+WriteVTK.json "tests_fail"
 XGBoost.json "tests_fail"
 XKPasswd.json "tests_pass"
 XMLconvert.json "tests_pass"
@@ -1306,7 +1306,7 @@
 YT.json "not_possible"
 ZChop.json "tests_pass"
 Zeros.json "tests_pass"
-ZipFile.json "tests_pass"
+ZipFile.json "tests_fail"
 Zlib.json "tests_fail"
 ZMQ.json "tests_pass"
 ZVSimulator.json "no_tests"

@yuyichao
Copy link
Contributor Author

yuyichao commented May 17, 2017

Unrelated failures

BayesianNonparametrics.jl

Test Failed
  Expression: model0.energy < model1.energy
   Evaluated: -3.9856272983096845 < -4.00667531764238
ERROR: LoadError: LoadError: There was an error during testing
while loading /home/vagrant/.julia/v0.7/BayesianNonparametrics/test/dpmTests.jl, in expression starting on line 26
while loading /home/vagrant/.julia/v0.7/BayesianNonparametrics/test/runtests.jl, in expression starting on line 7

Cxx.jl has a load failure

ERROR: LoadError: LoadError: LoadError: LoadError: could not load library "libcxxffi"
/home/vagrant/.julia/v0.7/Cxx/src/../deps/usr/lib/libcxxffi.so: undefined symbol: _ZTVN4llvm2cl3optISsLb0ENS0_6parserISsEEEE
Stacktrace:
 [1] dlopen(::String, ::UInt32) at ./libdl.jl:97
 [2] init_libcxxffi() at /home/vagrant/.julia/v0.7/Cxx/src/initialization.jl:21
 [3] include_from_node1(::String) at ./loading.jl:*563
 [4] include(::String) at ./sysimg.jl:14
 [5] include_from_node1(::String) at ./loading.jl:563
while loading /home/vagrant/.julia/v0.7/Cxx/src/initialization.jl, in expression starting on line 23
while loading /home/vagrant/.julia/v0.7/Cxx/src/Cxx.jl, in expression starting on line 163
while loading /home/vagrant/.julia/v0.7/Cxx/test/cxxstr.jl, in expression starting on line 1
while loading /home/vagrant/.julia/v0.7/Cxx/test/runtests.jl, in expression starting on line 1

VoronoiCells

Area of Voronoi cells: Test Failed
  Expression: abs(sum(A) - 1) < 0.0001
   Evaluated: 0.00018106122641303735 < 0.0001
Stacktrace:
 [1] macro expansion at /home/vagrant/.julia/v0.7/VoronoiCells/test/Voronoiarea.jl:20 [inlined]
 [2] macro expansion at ./test.jl:856 [inlined]
 [3] anonymous at ./<missing>:?
Area of Voronoi cells: Error During Test
  Got an exception of type ErrorException outside of a @test
  assertion failed: |A - A2| <= 3.469446951953614e-12
    A = [0.0189761, 0.00584947, 0.00463335, 0.0029174, 0.00828089, 0.019177, 0.0092254, 0.00495294, 0.00835396, 0.00548657, 0.00550654, 0.0137324, 0.00857214, 0.0088534, 0.00765243, 0.019756, 0.00624881, 0.0183264, 0.0131272, 0.0117197, 0.011981, 0.00202887, 0.0158496, 0.011952, 0.00832745, 0.00389998, 0.00938641, 0.00288458, 0.0199885, 0.0106022, 0.0114793, 0.0156345, 0.00193784, 0.0044089, 0.0103206, 0.0138874, 0.0110646, 0.00596281, 0.00704557, 0.0112337, 0.00983525, 0.0112152, 0.00351418, 0.0159648, 0.00599523, 0.00414084, 0.0111017, 0.0112431, 0.00735149, 0.0144064, 0.005341, 0.00827779, 0.0100523, 0.0068681, 0.0133736, 0.0114266, 0.00982489, 0.0278722, 0.0161176, 0.00832761, 0.0187617, 0.00517698, 0.00508053, 0.0194916, 0.0153735, 0.0133648, 0.00613633, 0.00464849, 0.00769056, 0.00690572, 0.0162479, 0.00642415, 0.0150212, 0.0113191, 0.00351618, 0.00495281, 0.0137348, 0.0034643, 0.00940754, 0.0156386, 0.0213498, 0.00739855, 0.00550543, 0.0133941, 0.0154983, 0.00150796, 0.0219578, 0.0055734, 0.00294187, 0.00403018, 0.00685664, 0.000477114, 0.0124685, 0.0207205, 0.00375992, 0.0134731, 0.00386068, 0.0155057, 0.008835, 0.00923614]
    A2 = [0.0189761, 0.00584947, 0.00463335, 0.0029174, 0.00828089, 0.019177, 0.0092254, 0.00495294, 0.00835396, 0.00548657, 0.00550654, 0.0137324, 0.00857214, 0.0088534, 0.00765243, 0.0200705, 0.00624881, 0.0183264, 0.0131272, 0.0117197, 0.011981, 0.00202887, 0.0158496, 0.011952, 0.00832745, 0.00389998, 0.00938641, 0.00288458, 0.0199885, 0.0106022, 0.0114793, 0.0156345, 0.00193784, 0.0044089, 0.0103206, 0.0138874, 0.0110646, 0.00596281, 0.00704557, 0.0112337, 0.00983525, 0.0112152, 0.00351418, 0.0159648, 0.00599523, 0.00414084, 0.0111017, 0.0112431, 0.00735149, 0.0144064, 0.005341, 0.00827779, 0.0100523, 0.0068681, 0.0133736, 0.0114266, 0.00982489, 0.0278722, 0.0161176, 0.00832761, 0.0187617, 0.00517698, 0.00508053, 0.0194916, 0.0153735, 0.0133648, 0.00613633, 0.00464849, 0.00769056, 0.00690572, 0.0157524, 0.00642415, 0.0150212, 0.0113191, 0.00351618, 0.00495281, 0.0137348, 0.0034643, 0.00940754, 0.0156386, 0.0213498, 0.00739855, 0.00550543, 0.0133941, 0.0154983, 0.00150796, 0.0219578, 0.0055734, 0.00294187, 0.00403018, 0.00685664, 0.000477114, 0.0124685, 0.0207205, 0.00375992, 0.0134731, 0.00386068, 0.0155057, 0.008835, 0.00923614]
    difference = 0.0004955270456197883 > 3.469446951953614e-12
  Stacktrace:
   [1] test_approx_eq(::Array{Float64,1}, ::Array{Float64,1}, ::Float64, ::String, ::String) at ./deprecated.jl:1011
   [2] test_approx_eq(::Array{Float64,1}, ::Array{Float64,1}, ::String, ::String) at ./deprecated.jl:1021
   [3] macro expansion at /home/vagrant/.julia/v0.7/VoronoiCells/test/Voronoiarea.jl:26 [inlined]
   [4] macro expansion at ./test.jl:856 [inlined]
   [5] anonymous at ./<missing>:?
   [6] include_from_node1(::String) at ./loading.jl:563
   [7] include(::String) at ./sysimg.jl:14
   [8] include_from_node1(::String) at ./loading.jl:563
   [9] include(::String) at ./sysimg.jl:14
   [10] process_options(::Base.JLOptions) at ./client.jl:305
   [11] _start() at ./client.jl:371
Test Summary:         | Fail  Error  Total
Area of Voronoi cells |    1      1      2
ERROR: LoadError: LoadError: Some tests did not pass: 0 passed, 1 failed, 1 errored, 0 broken.
while loading /home/vagrant/.julia/v0.7/VoronoiCells/test/Voronoiarea.jl, in expression starting on line 12
while loading /home/vagrant/.julia/v0.7/VoronoiCells/test/runtests.jl, in expression starting on line 1

Real bugs

  • Codecs
  • CRC
  • ImageCore
  • JPLEphemeris
  • LegacyStrings
  • MbedTLS
  • OpenEphysLoader
  • Pcap,
  • SHA
  • ZipFile

Failure due to dependency issue

  • BlossomV's failure comes from SHA (BinDeps)
  • Erdos's comes from BlossomV
  • ImageMagick's comes from ZipFile
  • NPZ's comes from ZipFile
  • StringEncodings from LegacyStrings
  • WriteVTK from SHA

This amount of breackage is not more than what I expected. I'll try to fix (i.e. PR) at least Codecs, CRC, ImageCore, LegacyStrings, MbedTLS, SHA, ZipFile before merging.

@yuyichao yuyichao deleted the yyc/align branch May 18, 2017 23:01
work = zeros(UInt64, JN32 >> 1)
dsfmt = Vector{UInt64}(nval >> 1)
ccall(:memcpy, Ptr{Void}, (Ptr{UInt64}, Ptr{Int32}, Csize_t),
dsfmt, val, (nval - 1) * sizeof(Int32))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As the last location of dsfmt::Vector{UInt64} below is overwritten, isn't it enough to copy (nval-2)*sizeof(Int32) in the memcpy here? Of course nothing wrong either.

@timholy
Copy link
Member

timholy commented May 23, 2017

Hmm, an interesting consequence here is that we now get errors when we try to mmap a UInt16 array starting at an odd-valued offset into the file: https://travis-ci.org/JuliaIO/NRRD.jl/jobs/235009267

To preserve the alignment, we'd have to make sure that the NRRD header's length is a multiple of sizeof(T). While NRRD.jl could quite easily enforce that for files that it writes, part of its job is to handle files "from the wild" which may not be so careful. I suppose one could create an AbstractArray type which uses unsafe_load in its implementation of getindex, but this seems a little ugly. Any other good ideas?

@yuyichao
Copy link
Contributor Author

we now get errors when we try to mmap a UInt16 array starting at an odd-valued offset into the file

This is exactly the type of error that this change is meant to catch #14885 (comment)

@yuyichao
Copy link
Contributor Author

The implementation of an array that provides unaligned access is exactly what I was suggesting in JuliaImages/ImageCore.jl#38 (comment) (though maybe not for the usage case in ImageCore). From the fixes I submitted, it seems that this could be useful as a package for memory mapped IO.

@vtjnash
Copy link
Member

vtjnash commented May 23, 2017

Since it doesn't matter on x86, presumably the C library just didn't care? Should we have a very_unsafe_wrap that skips the check?

@yuyichao
Copy link
Contributor Author

x86 will start to care when you reinterpret a vector Vector (.... ah I hate this overloaded meaning of vector)...... Unless there isn't any better solution (I think a unaligned array could be good) I'd like to not provide interfaces that lies to LLVM....

@timholy
Copy link
Member

timholy commented May 23, 2017

Because I thought a different approach would be better, I'd forgotten about your andrewcooke/CRC.jl#14. Sure, I'll grab that and polish it up and submit it as a JuliaArrays package.

@timholy
Copy link
Member

timholy commented May 23, 2017

@sbromberger
Copy link
Contributor

JLD2.jl is breaking because of this. Unfortunately, I have a lot of research data tied up in JLD2-formatted files that I can no longer access.

@timholy
Copy link
Member

timholy commented May 30, 2017

For the moment you should switch to 0.6-rc2, because that doesn't include this change.

I do worry that this change is pretty invasive to have at such a late moment in 0.6. Perhaps we shouldn't backport?

@sbromberger
Copy link
Contributor

For the moment you should switch to 0.6-rc2, because that doesn't include this change.

It's difficult for me to do that because I'm also in the middle of ensuring that LightGraphs and GraphIO play nicely with -nightly (until 0.6 is released, we're sort of in this strange situation where we have to make sure 0.6-rc* and 0.7 work).

@yuyichao
Copy link
Contributor Author

@timholy This will not be backported to 0.6. The part that should be is the first commit which is mentioned in #21831 (comment)

@sbromberger
Copy link
Contributor

I can confirm that JLD2 works without issues on -rc2. Thank you, @timholy.

tkelman pushed a commit that referenced this pull request Jun 3, 2017
This is undefined behavior in LLVM and can actually segfault on real hardware
including x86 in certain cases.

Also add missing endianess test since it is changed in this commit.

(cherry picked from commit 99286f9)
ref #21831
@quinnj
Copy link
Member

quinnj commented Jun 13, 2017

Am I correct in understanding that this PR disallows doing the following:

julia> t = zeros(UInt8, 2)
2-element Array{UInt8,1}:
 0x00
 0x00

julia> reinterpret(UInt16, t)
ERROR: ArgumentError: reinterpret from alignment 1 bytes to alignment 2 bytes not allowed
Stacktrace:
 [1] reinterpret(::Type{UInt16}, ::Array{UInt8,1}, ::Tuple{Int64}) at ./array.jl:160
 [2] reinterpret(::Type{UInt16}, ::Array{UInt8,1}) at ./array.jl:139

Do we really have to be this strict? And are there work-arounds? FWIW, this change broke FlatBuffers.jl, though I'm not sure why it didn't make it into all the discussions and PkgEval runs mentioned in this PR. But now I'm trying to figure it out; the use-case in FlatBuffers is that we essentially get binary blobs as inputs and decode structs and sometimes arrays of structs out of the binary blob; it seems a bit crazy to me if a Vector{UInt8} is now unable to be reinterpret-ed to anything larger than a byte. Am I missing something here?

@yuyichao
Copy link
Contributor Author

Do we really have to be this strict?

Yes.

it seems a bit crazy to me if a Vector{UInt8} is now unable to be reinterpret-ed to anything larger than a byte

This is actually exactly the wrong thing to do. Though more presicely, anything with alignment larger than a byte.

decode structs and sometimes arrays of structs out of the binary blob

Use unsafe_load.

@quinnj
Copy link
Member

quinnj commented Jun 13, 2017

And for an array we have to do something like [unsafe_load(ptr, i) for i = ....]?

@yuyichao
Copy link
Contributor Author

That's one way to do it. You can also use the unaligned vector mentioned above. Or allocate it with the correct type and reinterpret back for reading etc.

@simonster simonster added the needs news A NEWS entry is required for this change label Jun 19, 2017
sambitdash added a commit to sambitdash/PDFIO.jl that referenced this pull request Aug 24, 2017
@KristofferC KristofferC removed the needs news A NEWS entry is required for this change label Nov 13, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
breaking This change will break code system:arm ARMv7 and AArch64
Projects
None yet
Development

Successfully merging this pull request may close these issues.