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

Add optional -Werror flag #5

Merged
merged 30 commits into from
Oct 2, 2017
Merged

Add optional -Werror flag #5

merged 30 commits into from
Oct 2, 2017

Conversation

GretaCB
Copy link
Contributor

@GretaCB GretaCB commented Aug 30, 2017

Per #2

Next Actions

  • Fix current warnings (which are now erroring)
  • Set MAX for compress/decompress size
  • Remove std::string functions and only allow char * (per Update Readme #1 (comment))
  • Fix compile errors/Travis tests 🍏
  • Add tidy and format scripts
  • add handy Dockerfile
  • Code Review

cc @springmeyer @mapsam

CMakeLists.txt Outdated
option(WERROR "Add -Werror flag to build (turns warnings into errors)" ON)

# Note: -D_GLIBCXX_USE_CXX11_ABI=0 is needed to support mason packages that are precompiled libs
# Currently we only depend on a header only library, but this will help avoid issues when more libs are added via mason
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -pedantic -Wsign-compare -Wconversion -Wshadow")
Copy link
Contributor

Choose a reason for hiding this comment

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

Looks as if you grabbed the comments about -D_GLIBCXX_USE_CXX11_ABI=0 without the actual flag being added to the CMAKE_CXX_FLAGS? Best to pull that over too.

@springmeyer
Copy link
Contributor

@GretaCB just reviewed overall and have some suggestions to consider as you push tomorrow:

  1. Move to using CHECK_THROWS_WITH or REQUIRE_THROWS_WITH so you can start asserting on the message of the exception (since in the current state they are potentially going to change depending on debug or release mode). You can use catch::Contains to just assert on a substring like: CHECK_THROWS_WITH(gzip::compress(pointer, l), Catch::Contains("too large to fit into unsigned int type"));

  2. Since behavior may different depend on Debug/Release mode how about we change the makefile to test both when you run make test:

diff --git a/Makefile b/Makefile
index 179e1bb..75c578f 100644
--- a/Makefile
+++ b/Makefile
@@ -4,13 +4,16 @@ export WERROR ?= true
 default: release
 
 release:
-       mkdir -p build && cd build && cmake ../ -DCMAKE_BUILD_TYPE=Release -DWERROR=$(WERROR) && VERBOSE=1 cmake --build .
+       mkdir -p build/Release && cd build/Release && cmake ../../ -DCMAKE_BUILD_TYPE=Release -DWERROR=$(WERROR) && VERBOSE=1 cmake --build .
 
 debug:
-       mkdir -p build && cd build && cmake ../ -DCMAKE_BUILD_TYPE=Debug -DWERROR=$(WERROR) && VERBOSE=1 cmake --build .
+       mkdir -p build/Debug && cd build/Debug && cmake ../../ -DCMAKE_BUILD_TYPE=Debug -DWERROR=$(WERROR) && VERBOSE=1 cmake --build .
 
-test:
-       @if [ -f ./build/unit-tests ]; then ./build/unit-tests; else echo "Please run 'make release' or 'make debug' first" && exit 1; fi
+test: release debug
+       @echo "Running tests for Debug mode"
+       ./build/Debug/unit-tests
+       @echo "Running tests for Release mode"
+       ./build/Release/unit-tests
 
 tidy:
        ./scripts/clang-tidy.sh

@GretaCB
Copy link
Contributor Author

GretaCB commented Sep 1, 2017

@springmeyer I just pushed updates per chat earlier:

  • MAX_SIZE limits are now const and uneditable
  • Moved DEBUG tests into their own place. These work since the int overflow check happens before the max size check, but not sure if that will cause unnecessary tripups.
  • Also, not completely sure why the compress pointer test is failing. Assuming it has something to do with the size I'm passing in?

@springmeyer
Copy link
Contributor

MAX_SIZE limits are now const and uneditable

Great.

Moved DEBUG tests into their own place. These work since the int overflow check happens before the max size check, but not sure if that will cause unnecessary tripups.

Good call 👍

Also, not completely sure why the compress pointer test is failing. Assuming it has something to do with the size I'm passing in?

In the near term I think we should stop comparing lengths. Because there are legitimate reasons for the encoded string to be longer than the raw string. So we should do away with all these comparisons. That leaves the question of how to test. I think in the short term we could simply ensure round-tripping works. In the long germ I think we should move to having:

  • file based fixtures for input data
  • an adjacent file of gzip coded data
  • then compare them byte for byte
  • optional: add an UPDATE environment variable to be able to put the tests into a mode where they are updateable

This way we can ensure the output is exactly as we expect. And we would pick up differences, say, between our results and another implementation like #7.

@GretaCB GretaCB mentioned this pull request Sep 14, 2017
2 tasks
@GretaCB
Copy link
Contributor Author

GretaCB commented Sep 19, 2017

Ok cool so:

  • string param functions are gone
  • tests updated and passing locally
  • docs updated
  • asserts on test string results are patched for now. I'll split out @springmeyer 's suggestion above into a separate ticket for the future.

Now just need to troubleshoot the compile errors in Travis

@GretaCB
Copy link
Contributor Author

GretaCB commented Sep 22, 2017

Update

  • I was able to solve the a couple compiler errors:
  • I was unable to solve a memory leak error happening only during the sanitize Travis job. I attempted to replicate the leak and isolate one of the failing tests and take Catch out of the equation. I'm not 100% sure how to proceed to fully solve this.

@springmeyer
Copy link
Contributor

g++5's -fsanitize didnt like unsigned-integer-overflow. Solved the issue by not including the flag when compiler is GNU

I don't think we need/want to have -funsigned-integer-overflow in the CMakeLists.txt at all.We already apply it for a specific travis job for clang++. I'm comfortable just testing the sanitizers through clang++ and not g++. If we remove from the CmakeLists.txt then no custom handling will be needed.

Makefile Outdated
default: release

release:
mkdir -p build && cd build && cmake ../ -DCMAKE_BUILD_TYPE=Release && VERBOSE=1 cmake --build .
mkdir -p build/Release && cd build/Release && cmake ../../ -DCMAKE_BUILD_TYPE=Release -DWERROR=$(WERROR) && VERBOSE=1 cmake --build .
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@springmeyer I'm noticing this is much different than the bench and the hpp-skel master Makefiles. Curious if you have a preference. I also noticed that this conflicts with how clang-tidy runs (I have it setup locally, not in this branch). Perhaps it has something to do with the extra ../?

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm noticing this is much different than the bench and the hpp-skel master Makefiles.

This was done so we could have make test run both release and debug tests while developing. I think we should roll back to match hpp-skel now that development is slowing down.

I also noticed that this conflicts with how clang-tidy runs (I have it setup locally, not in this branch).

Whoops, that was an oversight. So, hopefully rolling back to match hpp-skel will help the clang-tidy scripts find things right.

Copy link
Contributor Author

@GretaCB GretaCB Sep 28, 2017

Choose a reason for hiding this comment

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

Syncing with master and I'll keep the WERROR flag in there

Copy link
Contributor Author

Choose a reason for hiding this comment

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

mmmm, perhaps only for Debug build

Makefile Outdated
mkdir -p build && cd build && cmake ../ -DCMAKE_BUILD_TYPE=Debug && VERBOSE=1 cmake --build .
mkdir -p build/Debug && cd build/Debug && cmake ../../ -DCMAKE_BUILD_TYPE=Debug -DWERROR=$(WERROR) && VERBOSE=1 cmake --build .

test: release debug
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I didnt merge the fancy if logic from master that checks for the existence of the unit-tests binary since we're compiling both debug and release during tests.

Makefile Outdated

bench:
@if [ -f ./build/bench-tests ]; then ./build/bench-tests; else echo "Please run 'make release' or 'make debug' first" && exit 1; fi

test: default
@if [ -f ./build/unit-tests ]; then ./build/unit-tests; else echo "Please run 'make release' or 'make debug' first" && exit 1; fi
tidy:
Copy link
Contributor Author

Choose a reason for hiding this comment

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

removing and will add in a separate branch

Makefile Outdated

coverage:
./scripts/coverage.sh

clean:
rm -rf build

format:
Copy link
Contributor Author

Choose a reason for hiding this comment

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

removing and will add in a separate branch

@GretaCB
Copy link
Contributor Author

GretaCB commented Sep 28, 2017

Shoot, after re-adding the tests, looks like a couple more errors popped up. Taking a peek. Also debugging the Dockerfile now that the make commands have changed.

@GretaCB
Copy link
Contributor Author

GretaCB commented Sep 28, 2017

Looks like we've got a segfault in the tests.

Trying to spin up the Docker image to try and recreate/troubleshoot, but the Dockerfile is failing when checking for the CXX compiler:

Carols-MacBook-Pro:gzip-hpp carol$ docker run -it --cap-add SYS_PTRACE gzip-hpp
mkdir -p build && cd build && cmake ../ -DCMAKE_BUILD_TYPE=Release && VERBOSE=1 cmake --build .
-- The CXX compiler identification is unknown
-- Check for working CXX compiler: /usr/local/src/.toolchain/bin/clang++
-- Check for working CXX compiler: /usr/local/src/.toolchain/bin/clang++ -- broken
CMake Error at mason_packages/linux-x86_64/cmake/3.8.2/share/cmake-3.8/Modules/CMakeTestCXXCompiler.cmake:44 (message):
  The C++ compiler "/usr/local/src/.toolchain/bin/clang++" is not able to
  compile a simple test program.

  It fails with the following output:

   Change Dir: /usr/local/src/build/CMakeFiles/CMakeTmp

  

  Run Build Command:"/usr/bin/make" "cmTC_207cd/fast"

  make[1]: Entering directory '/usr/local/src/build/CMakeFiles/CMakeTmp'

  /usr/bin/make -f CMakeFiles/cmTC_207cd.dir/build.make
  CMakeFiles/cmTC_207cd.dir/build

  make[2]: Entering directory '/usr/local/src/build/CMakeFiles/CMakeTmp'

  Building CXX object CMakeFiles/cmTC_207cd.dir/testCXXCompiler.cxx.o

  /usr/local/src/.toolchain/bin/clang++ -fsanitize=address,undefined
  -fno-sanitize-recover=all -o
  CMakeFiles/cmTC_207cd.dir/testCXXCompiler.cxx.o -c
  /usr/local/src/build/CMakeFiles/CMakeTmp/testCXXCompiler.cxx

  /usr/local/src/.toolchain/bin/clang++: 1:
  /usr/local/src/.toolchain/bin/clang++: Syntax error: "(" unexpected

  CMakeFiles/cmTC_207cd.dir/build.make:65: recipe for target
  'CMakeFiles/cmTC_207cd.dir/testCXXCompiler.cxx.o' failed

  make[2]: *** [CMakeFiles/cmTC_207cd.dir/testCXXCompiler.cxx.o] Error 2

  make[2]: Leaving directory '/usr/local/src/build/CMakeFiles/CMakeTmp'

  Makefile:126: recipe for target 'cmTC_207cd/fast' failed

  make[1]: *** [cmTC_207cd/fast] Error 2

  make[1]: Leaving directory '/usr/local/src/build/CMakeFiles/CMakeTmp'

  

  

  CMake will not be able to correctly generate this project.
Call Stack (most recent call first):
  CMakeLists.txt:2 (project)


-- Configuring incomplete, errors occurred!
See also "/usr/local/src/build/CMakeFiles/CMakeOutput.log".
See also "/usr/local/src/build/CMakeFiles/CMakeError.log".
Makefile:7: recipe for target 'release' failed
make: *** [release] Error 1

The same error occurs when I revert back to the Makefile we had earlier this week when we got the image compiling successfully.

@springmeyer
Copy link
Contributor

I'm not sure if docker ignores hidden directories in its COPY. If not then I wonder if the dockerfile problem is due to the .toolchain directory getting copied from your host to the container. Maybe try adding .toolchain to the .dockerignore and then rebuilding/running: does that allow the build in docker to work?

@GretaCB
Copy link
Contributor Author

GretaCB commented Sep 28, 2017

@springmeyer 👍 That did the trick. Uncovered another leak, diving in 🏊‍♀️

@springmeyer
Copy link
Contributor

Noticing the last commit failed only with clang++ and only with the release build. Very peculiar. It fails with:

round trip compression - gzip
  strategy - invalid compression
-------------------------------------------------------------------------------
/home/travis/build/mapbox/gzip-hpp/test/test.cpp:89
...............................................................................
/home/travis/build/mapbox/gzip-hpp/test/test.cpp:89: FAILED:
  {Unknown expression after the reported line}
with expansion:
due to a fatal error condition:
  SIGSEGV - Segmentation violation signal

https://travis-ci.org/mapbox/gzip-hpp/jobs/280809852#L638

Looks like that the gzip::compress segfaulting when 99 is passed for the strategy arg:

CHECK_THROWS(gzip::compress(pointer, data.size(), level, strategy));
.

Thoughts are:

  • catch.hpp catches the segfaul signal such that it is not possible for logbt to get a backtrace out. I've also found this to be an annoying default in catch so I often comment out this part of catch.hpp to re-enable the actual segfault
  • The fact that this is only crashing in release mode makes me wonder if this is triggering some kind of undefined behavior in zlib, which perhaps is not our problem but nevertheless a problem.

@springmeyer
Copy link
Contributor

Tried to replicate locally with the Dockerfile and could not (yet).

@springmeyer
Copy link
Contributor

was able to extract a crashlog using logbt on travis (werror...crash-debug):

Core was generated by `./build/unit-tests'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x0000000000454972 in deflateEnd ()
Thread 1 (LWP 6071):
#0  0x0000000000454972 in deflateEnd ()
#1  0x000000000040447d in gzip::compress(char const*, unsigned long, int, int) ()
#2  0x0000000000414aac in ____C_A_T_C_H____T_E_S_T____10() ()
#3  0x000000000042ec0b in Catch::RunContext::runCurrentTest(std::string&, std::string&) ()
#4  0x000000000041fd39 in Catch::RunContext::runTest(Catch::TestCase const&) ()
#5  0x0000000000405b9d in Catch::runTests(Catch::Ptr<Catch::Config> const&) ()
#6  0x00000000004399d7 in Catch::Session::run() ()
#7  0x00000000004130cb in main ()

@springmeyer
Copy link
Contributor

springmeyer commented Sep 28, 2017

^^ was missing line numbers since -g was not in the release flags (refs mapbox/hpp-skel#51). So I quickly added to get line numbers:

Core was generated by `./build/unit-tests'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x0000000000454972 in deflateEnd ()
Thread 1 (LWP 6153):
#0  0x0000000000454972 in deflateEnd ()
#1  0x000000000040447d in gzip::compress (data=0x75adf8 "this is a sentence that will be compressed into something", size=57, level=<optimized out>, strategy=<optimized out>) at /home/travis/build/mapbox/gzip-hpp/include/gzip/compress.hpp:31
#2  0x0000000000414aac in ____C_A_T_C_H____T_E_S_T____10 () at /home/travis/build/mapbox/gzip-hpp/test/test.cpp:94
#3  0x000000000042ec0b in Catch::TestCase::invoke (this=<optimized out>) at /home/travis/build/mapbox/gzip-hpp/test/catch.hpp:8136
#4  Catch::RunContext::invokeActiveTestCase (this=0x7ffee0395b48) at /home/travis/build/mapbox/gzip-hpp/test/catch.hpp:6697
#5  Catch::RunContext::runCurrentTest (this=0x7ffee0395b48, redirectedCout=..., redirectedCerr=...) at /home/travis/build/mapbox/gzip-hpp/test/catch.hpp:6664
#6  0x000000000041fd39 in Catch::RunContext::runTest (this=0x7ffee0395b48, testCase=...) at /home/travis/build/mapbox/gzip-hpp/test/catch.hpp:6477
#7  0x0000000000405b9d in Catch::runTests (config=...) at /home/travis/build/mapbox/gzip-hpp/test/catch.hpp:6837
#8  0x00000000004399d7 in Catch::Session::run (this=<optimized out>) at /home/travis/build/mapbox/gzip-hpp/test/catch.hpp:6971
#9  0x00000000004130cb in Catch::Session::run (this=0x7ffee0395d30, argc=1, argv=<optimized out>) at /home/travis/build/mapbox/gzip-hpp/test/catch.hpp:6924
#10 main (argc=<optimized out>, argv=<optimized out>) at /home/travis/build/mapbox/gzip-hpp/test/catch.hpp:11176

@GretaCB
Copy link
Contributor Author

GretaCB commented Sep 28, 2017

Amazing sleuthing @springmeyer , thank you for poking at this. Looks like it's crashing at deflateEnd(...):

    if (deflateInit2(&deflate_s, level, Z_DEFLATED, 31, 8, strategy) != Z_OK)
    {
        deflateEnd(&deflate_s); // explicitly end deflate to avoid memory leak
        throw std::runtime_error("deflate init failed");
    }

...wondering if it makes sense to end deflate here if deflate was never able to fully initiate.

@springmeyer
Copy link
Contributor

Removing deflateEnd like you did in a936540 looks like the right fix. This highlights for me that we are missing handling of errors in InflateInit2 (

inflateInit2(&inflate_s, 32 + 15);
) since we don't respond to a error return code there.

Overall, great work, stoked to see this 🍏!

@GretaCB
Copy link
Contributor Author

GretaCB commented Oct 2, 2017

Great catch @springmeyer . Committed the changes, Travis is 🍏 , going to 🚢 .

Next PR is for tidy/format.

@GretaCB GretaCB merged commit 55badfe into master Oct 2, 2017
@GretaCB GretaCB deleted the werror branch October 2, 2017 07:54
This was referenced Oct 2, 2017
@springmeyer
Copy link
Contributor

Noting here that this branch was a big lift because we had a number of aggressive warnings enabled which started error-ing when we added -Werror. Like this project, we'll want to consistently have these more aggressive warnings enabled (like -Wconversion which highlight potential integer overflow or truncation issues). So, linking to refs mapbox/cpp#37 from here so that others which follow refs mapbox/cpp#37 can see this effort (git github interlinking) and learn from it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants