-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Concurrent invocations of puts seem to interfere with each other #7978
Comments
I observed similar garbled output even after isolating |
Totally offtopic, but there's no need to do |
I can't reproduce this on Mac OSX. I don't think Crystal works fine on a Raspberry Pi. At least it's not something we officially support it so it'll be very hard for us to give help on this. |
I haven't observed this issue on Linux. Just on Raspberry Pi 3. Since Crystal works on Linux and RaspPi runs Linux, I figured Crystal would work on RaspPi if Crystal could be cross compiled to run on RaspPi (even if this configuration is not supported). Clearly, that is not the case :) |
i feel like this is a unique and specific use-case. it also can't be reproduced on WSL or native Debian |
I am not sure if this an issue with cross compilation (that is causing the compiled program to output garbage) or the Crystal compiler on Raspberry Pi. Any suggestions to verify this is welcome. So far, I have tried building Crystal on Raspberry Pi 3B by 1) using the cross-compiled compiler and 2) bootstrapping the compiler (crystal-lang/boostrap-script). First approach failed due to insufficient memory while the second failed due to failure in building ruby in the first stage of bootstrapping. That said, I am looking for a way to compile Crystal programs to run on Raspberry Pi 3B. Doing so on Raspberry Pi would be ideal. |
Rasp Pi 3B uses Armv7 (v7l) processor. (The target triple is armv6-unknown-linux-gnueabihf.) So, the above test fails. |
I did some digging with gdb. For this, I changed
to
When a single request was submitted to the server, I found all of the strings and
However, while When two concurrent requests were submitted to the server,
|
Changing |
There is an issue with hard/soft floats on ARM 32 targets. Specifying the target CPU while compiling may help LLVM backend to generate proper code (or not). |
@ysbaddaden if you are suggesting floating point calculations (not data movements) involving floating point values) pose issues on ARM 32 targets, then I doubt that is the case as I was able to generate garbled output with the below minimal program. require "kemal"
get "/random" do |env|
tmp1 = "%fms" % 3.333
puts tmp1
tmp2 = "%dms" % 3.333
puts tmp2
""
end
Kemal.config.logging = false
Kemal.config.port = 1234
puts "Serving at 0.0.0.0:1234"
Kemal.run Submitting a single request to the above server produces the following output:
To cross-compile the compiler,
It seems the format specifier for float (%f) is broken. |
Well, the stringifier for floats uses float arithmetic and that might be broken as @ysbaddaden mentioned. Why do you doubt that this could be the issue? Your example does actually support that. |
For %f we call sprintf, there might be an issue there. But it's hard if we can't reproduce it on Mac and Linux. |
@straight-shoota TIL stringifying float values involves floating point calculations/arithmetic operations :) That said, it seems the floating point operations (e.g., the division operation worked fine) in the application code seems to work fine while the ones used to stringifying floats seem to be broken. Nevertheless, I will check this. |
Don't use floats, at all. Use integers instead —and don't round a float! The problem with hard/soft floats is that the caller/called ABI doesn't expect the value in the same registers (cpu integers vs fpu registers), which results in garbage. |
The |
@asterite I was able to reproduce the issue in a Raspbian container running on a Linux host. The instructions to use the Docker image to create a compiler is available in docker-files repo. Once you have built the compiler and shards in the container, the issue can be repro-ed by building and executing the example. You will need to install curl in the container (via |
Is the linux host running on armv6 as well or is it an x86 architecture? Raspbian has an x86 variant, so I'm not sure. |
The Linux host is a x86 machine while the Raspbian is running on armv7l emulator. |
Please read the following:
Likely a duplicate of #6954 All ARM isues are related to a hard/soft float issue. Specifying a CPU when compiling may fix the issue (it did for my qemu raspbian image) or not (fails on scaleway armv7 server, and reportedly rpi3). Reproducing isn't an issue. It's quite easy to. The problem is understanding why LLVM won't enable hard floats when compiling. Maybe we miss some LLVM attributes on functions? I recently noticed that clang sets a bunch of them, related to FP and soft-float. |
Maybe I'm saying something stupid, but for hard float you should specify cpu, fpu and float abi: |
@konovod I tried doing this today but I gave up as I could not figure out how to pass these flags to LLVM compiler from the command line interface of crystal compiler. |
@ysbaddaden Thanks for the pointer. I read thru some of these while digging around. BTW, what is the best way to pass the compiler options mentioned by @konovod to LLVM via crystals CLI? That would allow more experimentation. |
What do you mean? |
Maybe we just miss the Maybe we miss the ability to trigger thumb mode; when |
@asterite I wasn't sure at which program point were the memory addresses getting messed up. So, I dug around and found that |
The failure occurs only when the require "kemal"
def foo()
tp1 = "%fms" % 3.333
puts tp1
tp2 = "%dms" % 3.333
puts tp2
end
foo() # call1
get "/random" do |env|
foo() # call2
""
end
Kemal.config.logging = false
Kemal.config.port = 1234
puts "Serving at 0.0.0.0:1234"
Kemal.run Output upon requesting http://127.0.0.1:1234/random
|
What happens if you just use http server from the standard library? I don't think kemal is involved here. |
The below snippet fails as well. require "http/server"
def foo()
tp1 = "%fms" % 3.333
puts tp1
tp2 = "%dms" % 3.333
puts tp2
end
foo() # call1
server = HTTP::Server.new do |ctxt|
foo() # call2
ctxt.response.print "Boo"
end
address = server.bind_tcp 1234
puts "Serving at #{address}"
server.listen Output
|
Cool! Now you could try reducing it to using spawn and Fiber.yield in between calls, and spawning a lot of fibers and see if it still reproduces. The less code we have that reproduces the problem, the easier to find the cause. |
(I'll send such code later today) |
@rvprasad Try this: chan = Channel(Nil).new
1000.times do |i|
spawn do
tp1 = "%fms" % 3.333
puts tp1
Fiber.yield
tp2 = "%dms" % 3.333
puts tp2
chan.send(nil)
end
end
1000.times do
chan.receive
end |
@asterite Thanks. I was able to repro the issue in the Docker container. spawn do
tp1 = "%fms" % 3.333
puts tp1
end
sleep(10) |
What output you get with that program? |
It produces the following output in a container.
|
But it works fine if you don't do it inside |
Yes. Also, output is fine when |
@ysbaddaden In the below snippet, The
Any ideas on what/where might be the issue? |
We save/restore FPU registers on ARM when switching fibers, and it leads to the same hard/soft float codegen bug. |
I want to experiment with different LLVM compiler flags during code generation, e.g., related to FPU and NEON. Any ideas where and how these flags can be added/modified/specified? |
I know this issue has been dormant for a couple of years, but I wanted to bring up that I have also experienced this, although it was much earlier this year. |
Since I am not sure if this is a Crystal issue or Kemal issue, I have reported this to the Kemal team as well (kemalcr/kemal#543).
Description
A simple server responds to get requests with random numbers in JSON format. When the server is running on a Raspberry Pi and
ab
tool is used to issue sequential requests to the server in quick succession, the output of the server on standard output is garbled.I am reporting the issue here as I am not sure if this is a crystal issue or a kemal issue.
Steps to Reproduce
ab -n 10 -c 1 http://127.0.0.1:1234/random?num=30
Expected behavior: The following or something similar should be seen in the terminal executing the server.
Actual behavior: The following is seen in the terminal executing the server.
Reproduces how often: Always
Versions
Crystal 0.29.0 (2019-07-20)
Kemal 0.25.2
LLVM: 6.0.1
Default target: arm-unknown-linux-gnueabihf
Linux master10 4.14.34-hypriotos-v7+ #1 SMP Sun Apr 22 14:57:31 UTC 2018 armv7l GNU/Linux
Additional Information
The object file of the crystal compiler was compiled on Ubuntu/Laptop and then linked to create the executable on Hypriot/RaspberryPi.
The text was updated successfully, but these errors were encountered: