Fix non standard C++ code constructs on Windows#4645
Fix non standard C++ code constructs on Windows#4645lizan merged 7 commits intoenvoyproxy:masterfrom greenhouse-org:msvc-changes
Conversation
1. Use STACK_ALLOC_ARRAY macro to allocate a variable-length array on the stack 2. Don't use designated initializers with structs 3. Remove usage of ?: operator 4. Use PACKED_STRUCT macro to typedef a packed struct Signed-off-by: Sam Smith <sesmith177@gmail.com>
Signed-off-by: Andrew Keesler <akeesler@pivotal.io> Signed-off-by: Sam Smith <sesmith177@gmail.com>
alyssawilk
left a comment
There was a problem hiding this comment.
Goodness, thanks for chasing all of these down!
Any chance you can find a regex which will catch most of these when folks do their fix_format? I'm concerned that we may otherwise end up with a game of whack-a-mole until we have a windows CI up and running, and it'd be nice if folks could catch these issues before hitting CI in any case.
|
|
||
| for (const Buffer::RawSlice& input_slice : slices) { | ||
| for (uint64_t i = 0; i < num_slices; i++) { | ||
| Buffer::RawSlice& input_slice = slices[i]; |
include/envoy/common/platform.h
Outdated
| #pragma once | ||
|
|
||
| // NOLINT(namespace-envoy) | ||
| #if !defined(WIN32) |
There was a problem hiding this comment.
I think those are compiler dependent so it should be !defined(_MSC_VER)? If someone uses LLVM on Windows then those should work.
- should fix build on OSX - add back missing const - STACK_ALLOC_ARRAY and PACKED_STRUCT macros based on compiler, not OS Signed-off-by: Arjun Sreedharan <asreedharan@pivotal.io>
- add checks for ?:, __attribute__((packed)) and designated initializers - fix additional usages found by these checks Signed-off-by: Sam Smith <sesmith177@gmail.com>
|
@alyssawilk we've added some checks to We didn't add a check for the variable length arrays because given: it is not possible to tell by regex if |
|
Can't we do best effort based on the Envoy style rules? If it's based on a constant it should be buf[FOO] or buf[FooLen] vs buf[foo_len] for variable length. I'm not entirely sure how consistent we are but worth giving it a try? |
Signed-off-by: Arjun Sreedharan <asreedharan@pivotal.io> Signed-off-by: Sam Smith <sesmith177@gmail.com>
|
It looks like there's still the case where the variable is declared envoy/source/common/runtime/runtime_impl.cc Lines 49 to 50 in e91ae86 constexpr (e.g. envoy/source/common/common/perf_annotation.cc Lines 84 to 85 in e91ae86 A simple regex would also flag |
alyssawilk
left a comment
There was a problem hiding this comment.
Argh, makes sense. Thanks for giving it a shot in any case, and I'm glad the other ones proved a bit helpful!
@mattklein123 @ggreenway @zuercher anyone up for a second pass?
|
Also the coverage build has been fixed, but you're going to need to merge master in order to pick the fix up. |
Signed-off-by: Arjun Sreedharan <asreedharan@pivotal.io> Signed-off-by: Sam Smith <sesmith177@gmail.com>
|
@sesmith177 @alyssawilk the check could be done via compiler flags to make it fail (at least for clang), use |
|
@lizan we could add |
Signed-off-by: Sam Smith <sesmith177@gmail.com> Signed-off-by: Arjun Sreedharan <asreedharan@pivotal.io>
|
@lizan can you merge if you are satisfied? |
| #include <malloc.h> | ||
|
|
||
| #define STACK_ALLOC_ARRAY(var, type, num) \ | ||
| type* var = static_cast<type*>(::_alloca(sizeof(type) * num)) |
There was a problem hiding this comment.
I just noticed this...does this actually work? What if 'type' has a constructor; it doesn't look like it would be called and you'd get uninitialized memory.
There was a problem hiding this comment.
you could loop over the array and used placed new, FWIW. You'd also need to take care of destructors.
There was a problem hiding this comment.
@jmarantz that's a good point -- the constructors/destructors definitely won't get called.
It works for now since the macro is only used with:
Buffer::RawSlicestruct iovecuint64_tunsigned char
and none of these types have constructors/destructors that do anything interesting. In the Buffer::RawSlice + struct iovec case, it looks like we always manually initialize the array (either through getRawSlices or looping over the array).
The best way to fix this probably depends on:
- how important it is that these arrays are on the stack
- does the solution need to be fully general or could we restrict it to the types above
There was a problem hiding this comment.
Great catch @jmarantz. @sesmith177 we definitely need to fix this somehow as it will produce a bunch of annoying and hard to find bugs. One option that comes to mind is having some wrapper RAII template object that does placement new and then would automatically do placement delete on scope exit?
There was a problem hiding this comment.
As an aside, could we just say that users have to compile Envoy with clang on windows? I'm wondering if that would also be a way to "fix" these problems?
There was a problem hiding this comment.
Another alternative here is to just edit the code-sites to just not use stack allocation. Is there a perf win from stack in this case? My thinking in general has been that if you want to have a lot of threads, then you don't want to allocate huge amounts of stack space to them, so you might not want to allocate potentially large things on the stack.
If that sounds right, I'd seal the deal by throwing a compile switch in clang to make that invalid, if such a switch exists (IIRC g++ has such a switch).
There was a problem hiding this comment.
A third option might be to use something like:
static_assert(std::is_trivially_destructible<type>::value, #type " must be trivially destructible");
in the macro/wrapper class to ensure that type has a trivial destructor and doesn't need to be deleted.
We're happy to go in any of the above directions.
It would be a significant effort to require clang on Windows. The tricky part would be ensuring that all third-party dependencies can be build with clang on Windows as well (i.e. do not require MSVC). When initially starting on this project, we made an attempt to compile everything with gcc/mingw, unfortunately there were dependencies that would not build on Windows with that toolchain.
There was a problem hiding this comment.
@mattklein123 @jmarantz We have a branch that replaces variable length arrays with std::vector (and adds -Wvla to ensure variable length arrays are invalid) here: https://github.com/greenhouse-org/envoy/commit/47c48a48f4ea71c00eb714674094bbd6d3d2a4c1
If it's decided that these arrays must be allocated on the stack, we will work on a wrapper template object and PR that instead
There was a problem hiding this comment.
I'm not in favor of switching to std::vector as I don't think we should take a perf hit due to a platform issue. If it's not too bad, I think I would go with the wrapper template. I don't think it will be that hard so can we try it first?
There was a problem hiding this comment.
Sounds good, we'll get that PR'd
Description:
As requested in #129, this is the first in a series of changes that will lead to Envoy building and running on Windows. To start, this PR fixes some non standard C++ code constructs that are not supported by MSVC:
These changes are necessary, but not sufficient, to get Envoy to compile on Windows
Risk Level:
Low
Testing:
bazel build //source/exe:envoy-static && bazel test //test/...Docs Changes:
N/A
Release Notes:
N/A