Skip to content

Commit

Permalink
Merge remote-tracking branch 'asf/9.2.x' into 9.2.x
Browse files Browse the repository at this point in the history
* asf/9.2.x:
  Updated ChangeLog
  Fix length bug in validate_unmapped_url_path (apache#8080)
  crash fix (apache#8268)
  test_MMH: fix memory leak in unit test (apache#8357)
  Doc: Add proxy.config.cacvhe.mutex_retry_delay (apache#8376)
  Add thread safety to PendingAction operations. (apache#8443)
  Report an error if configure can't find zlib (apache#8446)
  Update roadmap doc with latest releases (apache#8977)
  Setup UA consumer only if ua_entry is not nullptr (apache#8949)
  Update slice to only prefetch when first block is miss/hit-stale (apache#8890)
  Add RangeTransform::m_write_vio state checks (apache#8980)
  Fix compile on M1 Mac (apache#8999)
  Add stack guard pages (apache#8996)
  Fail fast on HTTP/2 header validation (apache#9009)
  Restrict unknown scheme of HTTP/2 request (apache#9010)
  Add content length mismatch check on handling HEADERS frame and CONTINUATION frame (apache#9012)
  Ignore POST request case from a check for background fill (apache#9013)
  Add back validatation that the scheme matches the wire protocol (apache#9005)
  Pin flask to version 2.1.3 (apache#9008)
  • Loading branch information
zwoop committed Aug 10, 2022
2 parents bb0e3cf + 3a16ac4 commit 5479b3e
Show file tree
Hide file tree
Showing 13 changed files with 162 additions and 37 deletions.
22 changes: 19 additions & 3 deletions CHANGELOG-9.2.0
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ Changes with Apache Traffic Server 9.2.0
#8075 - Add plugin parent_select reloading
#8076 - Fix plugin parent_select missing null checks.
#8078 - Clean up constructors and initialization in LogAccess class.
#8080 - Fix length bug in validate_unmapped_url_path
#8083 - Cancel active timeout when releasing session
#8084 - Defer canceling UA inactivity timeout for chunked bodies too
#8085 - Add cache condition in header_rewrite plugin for lookup results
Expand Down Expand Up @@ -226,7 +227,6 @@ Changes with Apache Traffic Server 9.2.0
#8187 - Ran clang-tidy over the master branch
#8188 - lua: add ts.is_debug_tag_set function
#8190 - Add TSMgmtConfigFileAdd api doc
#8191 - Fix error connection logging crash
#8194 - Remove global g_rec_config_contents_llq
#8201 - Fix H2 logic when setting EOS flag on DATA frame
#8204 - transaction data sink: only stream body bytes
Expand Down Expand Up @@ -260,6 +260,7 @@ Changes with Apache Traffic Server 9.2.0
#8264 - Prefetch plugin: add --fetch-query option
#8266 - Do not turn off cache for internal requests
#8267 - Align TS API Au test with Yahoo internal version.
#8268 - Avoid chunking in the post redirect case
#8269 - Fix leaks in ConfigManager::configName
#8271 - Add warning message about why enhance your calm is being sent
#8274 - Use better done file locations for some AuTests
Expand Down Expand Up @@ -303,6 +304,7 @@ Changes with Apache Traffic Server 9.2.0
#8348 - remove unused RecConfigFileEntry from RecConfigParse
#8354 - Adds support for TCP_NOTSENT_LOWAT sockopt
#8356 - free sessions when timeout
#8357 - test_MMH: fix memory leak in unit test
#8358 - Locking around SSLSecret::secret_map access
#8359 - Fix regex_remap plugin redirection.
#8360 - Stabilize regex_revalidate Au test.
Expand All @@ -313,6 +315,7 @@ Changes with Apache Traffic Server 9.2.0
#8372 - Add Au test for pqsi and pqsp log fields.
#8374 - 9.2.x autest fixes
#8375 - Add a set-http-cntl operator for header_rewrite
#8376 - Doc: Add proxy.config.cache.mutex_retry_delay
#8381 - Fix a potential H2 stall
#8392 - Update the feature lists available for autest
#8395 - Added metrics to the rate limit plugin and document the new options
Expand All @@ -334,7 +337,9 @@ Changes with Apache Traffic Server 9.2.0
#8435 - Fix unused-but-set-variable warnings
#8440 - Update the Multiplexer Docs for Multplexed HTTPS Connections
#8441 - bigobj: use automake to build test utilities
#8443 - Add thread safety to PendingAction operations.
#8445 - Include CPPFLAGS when building CompileParseRules
#8446 - Report an error if configure can't find zlib
#8449 - Add AuTest for HTTP CONNECT
#8450 - Document proxy.config.memory.max_usage
#8453 - Ignore ECONNABORTED on blocking accept
Expand Down Expand Up @@ -363,7 +368,6 @@ Changes with Apache Traffic Server 9.2.0
#8518 - Add 5xx's to be allowed to be used for simple retries
#8520 - Extend milestone api time tracking to remap.
#8523 - url_sig: change cleanup msg from TSError to TSDebug
#8524 - Set an appropriate callback function for OpenSSL 3
#8525 - Remove unused function "ats_mallopt"
#8531 - Destroy ssl context after use.
#8532 - Adds autest to test error cases loading ssl_multicert.config
Expand Down Expand Up @@ -485,6 +489,7 @@ Changes with Apache Traffic Server 9.2.0
#8882 - Make ats_scoped_obj a synonym for std::unique_ptr .
#8884 - Upgrade to Proxy Verifier 2.4.0.
#8886 - Add escape json for logging
#8890 - Update slice to only prefetch when first block is miss/hit-stale
#8892 - Cleanup SNIConfig
#8897 - Removed references to the throttle option from the slice plugin. (#8373)
#8898 - slice and cache_range_requests: allow header override (#8666)
Expand All @@ -493,7 +498,6 @@ Changes with Apache Traffic Server 9.2.0
#8909 - Move HKDF to OpenSSL 3 interfaces
#8924 - Update location for core rule set in modsecurity example
#8925 - Cleanup. Remove unnecessary use of a memory arena when logging.
#8926 - Allows errors from plugin initialization to bubble up
#8927 - Add docs for remap_stats plugin
#8928 - proxy_serve_stale: Test updates
#8931 - Fix clang-format installation with multiple threads
Expand All @@ -502,8 +506,20 @@ Changes with Apache Traffic Server 9.2.0
#8942 - Fix doc formatting for plugin remap_stats
#8943 - Fix doc formatting for rate_limit plugin
#8944 - Make the autopep8 clang-format targets quieter
#8949 - Setup UA consumer only if ua_entry is not nullptr
#8950 - .fit/fmt/.clang-format-installed prerequisite
#8965 - Proxy Verifier: Update to version 2.4.1
#8970 - add a metric to track how often the range seek bug is detected
#8971 - Fixes issue with file size calculation for existing logs
#8975 - Fix reverting PR#7302
#8977 - Update roadmap doc with latest releases
#8980 - Add RangeTransform::m_write_vio state checks
#8996 - Add stack guard pages
#8999 - Fix compile on M1 Mac
#9005 - Add back validatation that the scheme matches the wire protocol
#9008 - Pin flask to version 2.1.3
#9009 - Fail fast on HTTP/2 header validation
#9010 - Restrict unknown scheme of HTTP/2 request
#9011 - Add control char check in MIME Parser
#9012 - Add content length mismatch check on handling HEADERS frame and CONTINUATION frame
#9013 - Ignore POST request case from a check for background fill
3 changes: 3 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -1390,6 +1390,9 @@ AM_CONDITIONAL([BUILD_JA3_PLUGIN], [test "x${enable_ja3_plugin}" = "xyes"])
#
# Check for zlib presence and usability
TS_CHECK_ZLIB
if test "x${enable_zlib}" != "xyes"; then
AC_MSG_ERROR([Cannot find zlib library. Configure --with-zlib=DIR])
fi

#
# Check for lzma presence and usability
Expand Down
11 changes: 11 additions & 0 deletions doc/admin-guide/files/records.config.en.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2428,6 +2428,17 @@ Cache Control
write vector. For further details on cache write vectors, refer to the
developer documentation for :cpp:class:`CacheVC`.

.. ts::cv:: CONFIG proxy.config.cache.mutex_retry_delay INT 2
:reloadable:
:units: milliseconds

The retry delay for missing a lock on a mutex in the cache component. This is used generically
for most locks, except those that have an explicit configuration for the retry delay. For
instance, if the cache component is notifying another continuation of a cache event and fails to
get the lock for that continuation, it will use this as the delay for the retry. This is also
used from the asynchronous IO threads when IO finishes and the ``CacheVC`` lock or stripe lock is
required.

RAM Cache
=========

Expand Down
6 changes: 4 additions & 2 deletions doc/release-notes/roadmap.en.rst
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,10 @@ ATS Release Roadmap
:maxdepth: 1

Apache Traffic Server is currently on a two year major release cycle. At any
given time, we guarantee to have two major versions supported. Currently,
this means v7.1.x and v8.0.x, with a possible v8.1.x coming.
given time, we guarantee to have two major versions supported. Please refer to
our `download page <https://trafficserver.apache.org/downloads>`_ to see the
current supported versions.


For details on the actual developer release process, See

Expand Down
42 changes: 30 additions & 12 deletions include/tscore/PendingAction.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,13 +73,15 @@ class PendingAction
*
* @param action @c Action to check.
*
* @return @c true if the action was cleared, @c false if not.
*
* This clears the internal pointer without any side effect. it is used when the @c Action
* is handled and therefore should no longer be canceled.
*/
void clear_if_action_is(Action *action);
bool clear_if_action_is(Action *action);

private:
Action *pending_action = nullptr;
std::atomic<Action *> pending_action = nullptr;
};

inline bool
Expand All @@ -91,22 +93,32 @@ PendingAction::empty() const
inline PendingAction &
PendingAction::operator=(Action *action)
{
// Apparently HttpSM depends on not canceling the previous action if anew
// Apparently @c HttpSM depends on not canceling the previous action if a new
// one completes immediately. Canceling the contained action in that case
// cause the HttpSm to permanently stall.
// cause the @c HttpSM to permanently stall.
if (ACTION_RESULT_DONE != action) {
if (action != pending_action && pending_action != nullptr) {
pending_action->cancel();
Action *expected; // Need for exchange, and to load @a pending_action only once.
// Avoid race conditions - for each assigned action, ensure exactly one thread
// cancels it. Assigning @a expected in the @c while expression avoids potential
// races if two calls to this method have the same @a action.
while ((expected = pending_action) != action) {
if (pending_action.compare_exchange_strong(expected, action)) {
// This thread did the swap and now no other thread can get @a expected which
// must be canceled if it's not @c nullptr and then this thread is done.
if (expected != nullptr) {
expected->cancel();
}
break;
}
}
pending_action = action;
}
return *this;
}

inline Continuation *
PendingAction::get_continuation() const
{
return pending_action ? pending_action->continuation : nullptr;
return pending_action ? pending_action.load()->continuation : nullptr;
}

inline Action *
Expand All @@ -118,14 +130,20 @@ PendingAction::get() const
inline PendingAction::~PendingAction()
{
if (pending_action) {
pending_action->cancel();
pending_action.load()->cancel();
}
}

inline void
inline bool
PendingAction::clear_if_action_is(Action *action)
{
if (action == pending_action) {
pending_action = nullptr;
if (action != nullptr) {
while (action == pending_action) {
if (pending_action.compare_exchange_strong(action, nullptr)) {
// do NOT cancel - this is called when the event is handled.
return true;
}
}
}
return false;
}
60 changes: 53 additions & 7 deletions iocore/eventsystem/UnixEventProcessor.cc
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,16 @@ class ThreadAffinityInitializer : public Continuation
void init();
/// Set the affinity for the current thread.
int set_affinity(int, Event *);
/// Allocate a stack.
/// Allocate a stack and set guard pages.
/// @internal This is the external entry point and is different depending on
/// whether HWLOC is enabled.
void *alloc_stack(EThread *t, size_t stacksize);

protected:
/// Allocate a hugepage stack.
/// If huge pages are not enable, allocate a basic stack.
void *alloc_hugepage_stack(size_t stacksize);
void *do_alloc_stack(size_t stacksize);
void setup_stack_guard(void *stack, int stackguard_pages);

#if TS_USE_HWLOC

Expand Down Expand Up @@ -136,10 +137,55 @@ class ThreadInitByFunc : public Continuation
} Thread_Init_Func;
} // namespace

void
ThreadAffinityInitializer::setup_stack_guard(void *stack, int stackguard_pages)
{
#if !(defined(__i386__) || defined(__x86_64__) || defined(__arm__) || defined(__arm64__) || defined(__aarch64__) || \
defined(__mips__))
#error Unknown stack growth direction. Determine the stack growth direction of your platform.
// If your stack grows upwards, you need to change this function and the calculation of stack_begin in do_alloc_stack.
#endif
// Assumption: stack grows down
if (stackguard_pages <= 0) {
return;
}

size_t pagesize = ats_hugepage_enabled() ? ats_hugepage_size() : ats_pagesize();
size_t guardsize = stackguard_pages * pagesize;
int ret = mprotect(stack, guardsize, 0);
if (ret != 0) {
Fatal("Failed to set up stack guard pages: %s (%d)", strerror(errno), errno);
}
}

void *
ThreadAffinityInitializer::alloc_hugepage_stack(size_t stacksize)
ThreadAffinityInitializer::do_alloc_stack(size_t stacksize)
{
return ats_hugepage_enabled() ? ats_alloc_hugepage(stacksize) : ats_memalign(ats_pagesize(), stacksize);
size_t pagesize = ats_hugepage_enabled() ? ats_hugepage_size() : ats_pagesize();
int stackguard_pages;
REC_ReadConfigInteger(stackguard_pages, "proxy.config.thread.default.stackguard_pages");
ink_release_assert(stackguard_pages >= 0);

size_t size = INK_ALIGN(stacksize + stackguard_pages * pagesize, pagesize);
int mmap_flags = MAP_PRIVATE | MAP_ANONYMOUS;
#ifdef MAP_HUGETLB
if (ats_hugepage_enabled()) {
mmap_flags |= MAP_HUGETLB;
}
#endif
void *stack_and_guard = mmap(nullptr, size, PROT_READ | PROT_WRITE, mmap_flags, -1, 0);
if (stack_and_guard == MAP_FAILED) {
Error("Failed to allocate stack pages: size = %zu", size);
return nullptr;
}

setup_stack_guard(stack_and_guard, stackguard_pages);

void *stack_begin = static_cast<char *>(stack_and_guard) + stackguard_pages * pagesize;
Debug("iocore_thread", "Allocated %zu bytes (%zu bytes in guard pages) for stack {%p-%p guard, %p-%p stack}", size,
stackguard_pages * pagesize, stack_and_guard, stack_begin, stack_begin, static_cast<char *>(stack_begin) + stacksize);

return stack_begin;
}

#if TS_USE_HWLOC
Expand Down Expand Up @@ -239,7 +285,7 @@ ThreadAffinityInitializer::alloc_numa_stack(EThread *t, size_t stacksize)
}

// Alloc our stack
stack = this->alloc_hugepage_stack(stacksize);
stack = this->do_alloc_stack(stacksize);

if (mem_policy != HWLOC_MEMBIND_DEFAULT) {
// Now let's set it back to default for this thread.
Expand All @@ -260,7 +306,7 @@ ThreadAffinityInitializer::alloc_numa_stack(EThread *t, size_t stacksize)
void *
ThreadAffinityInitializer::alloc_stack(EThread *t, size_t stacksize)
{
return this->obj_count > 0 ? this->alloc_numa_stack(t, stacksize) : this->alloc_hugepage_stack(stacksize);
return this->obj_count > 0 ? this->alloc_numa_stack(t, stacksize) : this->do_alloc_stack(stacksize);
}

#else
Expand All @@ -279,7 +325,7 @@ ThreadAffinityInitializer::set_affinity(int, Event *)
void *
ThreadAffinityInitializer::alloc_stack(EThread *, size_t stacksize)
{
return this->alloc_hugepage_stack(stacksize);
return this->do_alloc_stack(stacksize);
}

#endif // TS_USE_HWLOC
Expand Down
2 changes: 2 additions & 0 deletions mgmt/RecordsConfig.cc
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,8 @@ static const RecordElement RecordsConfig[] =
,
{RECT_CONFIG, "proxy.config.thread.default.stacksize", RECD_INT, "1048576", RECU_RESTART_TS, RR_NULL, RECC_INT, "[131072-104857600]", RECA_READ_ONLY}
,
{RECT_CONFIG, "proxy.config.thread.default.stackguard_pages", RECD_INT, "1", RECU_RESTART_TS, RR_NULL, RECC_INT, "[1-256]", RECA_READ_ONLY}
,
{RECT_CONFIG, "proxy.config.restart.active_client_threshold", RECD_INT, "0", RECU_DYNAMIC, RR_NULL, RECC_NULL, nullptr, RECA_NULL}
,
{RECT_CONFIG, "proxy.config.restart.stop_listening", RECD_INT, "0", RECU_DYNAMIC, RR_NULL, RECC_INT, "[0-1]", RECA_NULL}
Expand Down
8 changes: 7 additions & 1 deletion proxy/Transform.cc
Original file line number Diff line number Diff line change
Expand Up @@ -791,7 +791,9 @@ RangeTransform::handle_event(int event, void *edata)
} else {
switch (event) {
case VC_EVENT_ERROR:
m_write_vio.cont->handleEvent(VC_EVENT_ERROR, &m_write_vio);
if (m_write_vio.cont) {
m_write_vio.cont->handleEvent(VC_EVENT_ERROR, &m_write_vio);
}
break;
case VC_EVENT_WRITE_COMPLETE:
ink_assert(m_output_vio == (VIO *)edata);
Expand All @@ -814,6 +816,10 @@ RangeTransform::handle_event(int event, void *edata)
}
}

if (!m_write_vio.mutex) {
return 0;
}

MUTEX_TRY_LOCK(trylock, m_write_vio.mutex, this_ethread());
if (!trylock.is_locked()) {
retry(10);
Expand Down
25 changes: 15 additions & 10 deletions proxy/http/HttpSM.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6049,6 +6049,7 @@ HttpSM::do_setup_post_tunnel(HttpVC_t to_vc_type)
// When redirect in process is true and redirection is enabled
// add http server as the consumer
if (post_redirect) {
chunked = false;
HTTP_SM_SET_DEFAULT_HANDLER(&HttpSM::tunnel_handler_for_partial_post);
tunnel.add_consumer(server_entry->vc, HTTP_TUNNEL_STATIC_PRODUCER, &HttpSM::tunnel_handler_post_server, HT_HTTP_SERVER,
"redirect http server post");
Expand Down Expand Up @@ -6683,18 +6684,22 @@ HttpSM::setup_internal_transfer(HttpSMHandler handler_arg)

HTTP_SM_SET_DEFAULT_HANDLER(handler_arg);

// Clear the decks before we setup the new producers
// As things stand, we cannot have two static producers operating at
// once
tunnel.reset();
if (ua_entry && ua_entry->vc) {
// Clear the decks before we setup the new producers
// As things stand, we cannot have two static producers operating at
// once
tunnel.reset();

// Setup the tunnel to the client
HttpTunnelProducer *p =
tunnel.add_producer(HTTP_TUNNEL_STATIC_PRODUCER, nbytes, buf_start, (HttpProducerHandler) nullptr, HT_STATIC, "internal msg");
tunnel.add_consumer(ua_entry->vc, HTTP_TUNNEL_STATIC_PRODUCER, &HttpSM::tunnel_handler_ua, HT_HTTP_CLIENT, "user agent");
// Setup the tunnel to the client
HttpTunnelProducer *p =
tunnel.add_producer(HTTP_TUNNEL_STATIC_PRODUCER, nbytes, buf_start, (HttpProducerHandler) nullptr, HT_STATIC, "internal msg");
tunnel.add_consumer(ua_entry->vc, HTTP_TUNNEL_STATIC_PRODUCER, &HttpSM::tunnel_handler_ua, HT_HTTP_CLIENT, "user agent");

ua_entry->in_tunnel = true;
tunnel.tunnel_run(p);
ua_entry->in_tunnel = true;
tunnel.tunnel_run(p);
} else {
(this->*default_handler)(HTTP_TUNNEL_EVENT_DONE, &tunnel);
}
}

// int HttpSM::find_http_resp_buffer_size(int cl)
Expand Down
Loading

0 comments on commit 5479b3e

Please sign in to comment.