test: remove the manual declarations of TestThread and figure it out from the platform.#18557
test: remove the manual declarations of TestThread and figure it out from the platform.#18557snowp merged 25 commits intoenvoyproxy:mainfrom
Conversation
Signed-off-by: Joshua Marantz <jmarantz@google.com>
Signed-off-by: Joshua Marantz <jmarantz@google.com>
Signed-off-by: Joshua Marantz <jmarantz@google.com>
|
Elisha -- FYI this should do the job. I am waiting for CI to tell me that Windows and Mac tests still work. |
|
This iteration fails Windows CI because Looking at mitigations. |
…ting in some contexts. Signed-off-by: Joshua Marantz <jmarantz@google.com>
Signed-off-by: Joshua Marantz <jmarantz@google.com>
Signed-off-by: Joshua Marantz <jmarantz@google.com>
…c went down. Signed-off-by: Joshua Marantz <jmarantz@google.com>
Signed-off-by: Joshua Marantz <jmarantz@google.com>
|
/assign-from @envoyproxy/first-pass-reviewers |
|
@envoyproxy/first-pass-reviewers assignee is @RyanTheOptimist |
Signed-off-by: Joshua Marantz <jmarantz@google.com>
Signed-off-by: Joshua Marantz <jmarantz@google.com>
source/common/common/thread.cc
Outdated
| #elif defined(__APPLE__) | ||
| return pthread_main_np() != 0; | ||
| #else | ||
| return true; |
There was a problem hiding this comment.
@davinci26 @wrowe is there an approach that would work in Windows?
There was a problem hiding this comment.
I don't know on top of my head, I am looking into it.
There was a problem hiding this comment.
If I'm understanding this change correctly, it seems like on Windows this change would mean that isMainOrTestThread() would always return true. Presumably that is ok? Would that not cause problems?
Are linux and APPLE the only two non-Windows platforms we build on? If so, those would fall into the "return true" block. I wonder if it might be wise to something like:
#elif defined(WIN32)
return true;
#else
static_assert(false, "unknown platform");
#endif
In case we end up with such a platform down the road. (Fuscia or FreeBSD or something)
There was a problem hiding this comment.
Yeah I think it would cause problems if we did an ASSERT(!isMainTestOrThread()), so I've gone with a strategy more like what you suggested.
There was a problem hiding this comment.
Windows might be tricky to support due to the way the threading model works. Can you open an issue and I will pick it up at some point
There was a problem hiding this comment.
Added in #18669 -- this is not a blocker for this PR though.
There was a problem hiding this comment.
Agreed, Windows benefit implicitly from this change just by having better test coverage on Linux. I want to provide parity as external filter writers might need this feature when they test their filters on windows
|
I'm reconsidering this approach -- I think we should have the checks all be macro-based so they can be a no-op on unsupported platforms. |
Signed-off-by: Joshua Marantz <jmarantz@google.com>
Signed-off-by: Joshua Marantz <jmarantz@google.com>
… touched by this PR Signed-off-by: Joshua Marantz <jmarantz@google.com>
Signed-off-by: Joshua Marantz <jmarantz@google.com>
…s where we cannot determine whether we are in the test thread. That way we get compile errors rather than assertions -- faster to fix. Signed-off-by: Joshua Marantz <jmarantz@google.com>
|
I tested this out with some internal code we have that has been fighting against the thread checks: it calls into code that reuses Envoy code from an arbitrary thread, and at times this will hit code paths that try to verify that code is done on main/test thread (though this check is not very meaningful in this custom context). We've been working around it for now by marking the context as a TestThread (very hacky, but works), and with this PR it seems like there is no way around the thread check. Would it be a lot of work to keep TestThread working the way it does, or provide some alternative? One alternative I could think of would be an RAII handle that would allow disabling thread checks for some time. |
|
I'm going to assign this over to @snowp to make sure this ends up working for our internal use case as well. |
|
Ah glad I got some feedback on this before pushing forward. The problem with the prior state where TestThread was declared by the test infrastructure is that we had a ton of tests that included Envoy code, but not its test infrastructure. So the code that declared the TestThread from test_runner.cc did not get called. But we could OR that all together and let you still declare a manual TestThread if you want to. Do you need to declare multiple distinct TestThread objects at the same time? Or do you just instantiate TestThread around a call that might do some checking? |
|
The way it works right now is that we just wrap offending code with I think ideally we'd have something like a |
Signed-off-by: Joshua Marantz <jmarantz@google.com>
|
IgnoreThreadChecks as an RAII context seems feasible to me. I'm curious what scenarios though you are calling something that is asserting to be on a thread where you want to disable that. I think to implement this, only the ASSERT_IS_TEST_THREAD type assertions defined in thread.h should be affected, right? E.g. you might have ASSERT(MainThread::isTestThread()) and you want that to be ignored, but you might also have ASSERT(!MainThread::IsTestThread()) that you'd also want to skip, and it'd be hard to do that from inside the impl if So is it OK to have the IgnoreThreadChecks only on the new ASSERT_ macros defined here? |
|
The first cases of this we've hit is trying to convert YAML to protobuf: Our use case is related to envoy-mobile: we're having the platform call into native code to initialize a subsystem, which attempts to parse YAML configuration that is provided by the function. This happens independently of EM startup, so the code may run on any thread. A bunch of the thread assertions in Envoy rely on the delineation between the main thread and worker threads, but this falls apart in envoy-mobile contexts where there are a lot of other threads in play, so we're hoping to just be able to bypass these checks when running outside of the EM event loops. |
|
Is it possible for us to engineer So, if we are committed to the goal of not having exceptions caught on the worker thread, a better way to do that is to leave a trail of harder-to-resolve issues to tackle later (TRY_NEEDS_AUDIT) than to just disable the check. If that strategy works for you I can leave this PR as is. If we'd rather not go in that direction then an |
Signed-off-by: Joshua Marantz <jmarantz@google.com>
|
For the sake of argument I added the hook to override the threading macros, though I'm not totally convinced they are the right thing. But in the spirit of not getting bogged down I've added it; happy to remove it by reverting 4f42287. |
|
It wouldn't be hard to change the serialization functions to not assert a main thread, but it gives raise to what appears to be a conflict of interest: within the Envoy code base we want to ensure that exceptions are only used on the main thread, but code outside of the repo may want to call it without thread checks. One option would be to reimplement this function (and any other function that this might apply to) outside of Envoy main. From our perspective it's a bit unfortunate to not be able to reuse code that already does exactly what we want, but I guess it depends on how intrusive it would be to support overriding the checks? @mattklein123 Do you have any thoughts here? |
It's seems reasonable to me to allow the default implementations to be overriden in a custom main? |
|
OK, makes sense to me. In that case does this patch look like it works for you? If so I can add some more comments and address other issues you might have. |
snowp
left a comment
There was a problem hiding this comment.
This LGTM, thanks for iterating!
|
Can you merge main and we'll get this in? |
Signed-off-by: Joshua Marantz <jmarantz@google.com>
Signed-off-by: Joshua Marantz <jmarantz@google.com>
|
merged. Also filled in some comments dismissing your approval :) |
|
/retest |
|
Retrying Azure Pipelines: |
Commit Message: Earlier attempts to integrate a requirement to manually declare TestThread made it too hard to integrate with other repos that depend on Envoy, but not on all its test infrastructure.
Instead, this PR uses platform-specific mechanisms to determine whether the current thread is the 'test' thread (ie the thread in main()). This makes it unnecessary to declare TestThread anywhere. However, the TestThread empty struct is left in the codebase for now to avoid adding more conflicts with other repos. It can be removed in a month or so.
A new RAII construct
SkipAssertsis added as an escape for scenarios where we are integrating Envoy code in a context where the thread-checking is not relevant.Additional Description:
Risk Level: low
Testing: //test/...
Docs Changes: n/a
Release Notes: n/a
Platform Specific Features: n/a