You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by du...@apache.org on 2019/06/24 14:47:41 UTC

[trafficserver] branch master updated: emergency shutdown

This is an automated email from the ASF dual-hosted git repository.

duke8253 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git


The following commit(s) were added to refs/heads/master by this push:
     new 5a8beee  emergency shutdown
5a8beee is described below

commit 5a8beee1b971db12ae9be6d406b0c1dcd4d4981e
Author: Fei Deng <du...@gmail.com>
AuthorDate: Mon Jun 17 15:21:04 2019 -0500

    emergency shutdown
---
 doc/developer-guide/api/functions/TSDebug.en.rst | 17 +++++-
 include/ts/ts.h                                  |  3 ++
 src/traffic_server/InkAPI.cc                     | 20 +++++++
 tests/gold_tests/shutdown/emergency.test.py      | 51 ++++++++++++++++++
 tests/gold_tests/shutdown/fatal.test.py          | 51 ++++++++++++++++++
 tests/tools/plugins/emergency_shutdown.cc        | 66 ++++++++++++++++++++++++
 tests/tools/plugins/fatal_shutdown.cc            | 66 ++++++++++++++++++++++++
 7 files changed, 273 insertions(+), 1 deletion(-)

diff --git a/doc/developer-guide/api/functions/TSDebug.en.rst b/doc/developer-guide/api/functions/TSDebug.en.rst
index 14702c4..110131b 100644
--- a/doc/developer-guide/api/functions/TSDebug.en.rst
+++ b/doc/developer-guide/api/functions/TSDebug.en.rst
@@ -28,8 +28,10 @@ Synopsis
 
 `#include <ts/ts.h>`
 
+.. function:: void TSError(const char * format, ...)
+.. function:: void TSFatal(const char * format, ...)
+.. function:: void TSEmergency(const char * format, ...)
 .. function:: void TSDebug(const char * tag, const char * format, ...)
-.. function:: void TSError(const char * tag, const char * format, ...)
 .. function:: int TSIsDebugTagSet(const char * tag)
 .. function:: void TSDebugSpecific(int debug_flag, const char * tag, const char * format, ...)
 .. function:: void TSHttpTxnDebugSet(TSHttpTxn txnp, int on)
@@ -49,6 +51,19 @@ Description
 of writing the output to the C standard output, it writes output
 to the Traffic Server error log.
 
+:func:`TSFatal` is used to shutdown Traffic Server in hopes that a clean
+restart will be able to fix the problem. It will also log a message to the
+Traffic Server error log just like :func:`TSError`.
+
+:func:`TSEmergency` is used to shutdown Traffic Server when restarting
+isn't sufficient to fix the problem, e.g. missing or corrupted files. It will
+also log a message to the Traffic Server error log just like :func:`TSError`.
+
+.. note::
+    Both :func:`TSFatal` and :func:`TSEmergency` can be called within
+    :func:`TSPluginInit`, such that Traffic Server can be shutdown promptly when
+    the plugin fails to initialize properly.
+
 :func:`TSDebug` is the same as :func:`TSError` except that it only
 logs the debug message if the given debug :arg:`tag` is enabled. It writes
 output to the Traffic Server debug log.
diff --git a/include/ts/ts.h b/include/ts/ts.h
index 6673000..fd91b83 100644
--- a/include/ts/ts.h
+++ b/include/ts/ts.h
@@ -261,6 +261,9 @@ tsapi char *TSfgets(TSFile filep, char *buf, size_t length);
 */
 tsapi void TSError(const char *fmt, ...) TS_PRINTFLIKE(1, 2);
 
+tsapi void TSEmergency(const char *fmt, ...) TS_PRINTFLIKE(1, 2);
+tsapi void TSFatal(const char *fmt, ...) TS_PRINTFLIKE(1, 2);
+
 /* --------------------------------------------------------------------------
    Assertions */
 tsapi void _TSReleaseAssert(const char *txt, const char *f, int l) TS_NORETURN;
diff --git a/src/traffic_server/InkAPI.cc b/src/traffic_server/InkAPI.cc
index 0480489..316282b 100644
--- a/src/traffic_server/InkAPI.cc
+++ b/src/traffic_server/InkAPI.cc
@@ -415,6 +415,26 @@ TSError(const char *fmt, ...)
   va_end(args);
 }
 
+tsapi void
+TSEmergency(const char *fmt, ...)
+{
+  va_list args;
+
+  va_start(args, fmt);
+  EmergencyV(fmt, args);
+  va_end(args);
+}
+
+tsapi void
+TSFatal(const char *fmt, ...)
+{
+  va_list args;
+
+  va_start(args, fmt);
+  FatalV(fmt, args);
+  va_end(args);
+}
+
 // Assert in debug AND optim
 void
 _TSReleaseAssert(const char *text, const char *file, int line)
diff --git a/tests/gold_tests/shutdown/emergency.test.py b/tests/gold_tests/shutdown/emergency.test.py
new file mode 100644
index 0000000..ab8a6b0
--- /dev/null
+++ b/tests/gold_tests/shutdown/emergency.test.py
@@ -0,0 +1,51 @@
+'''
+'''
+#  Licensed to the Apache Software Foundation (ASF) under one
+#  or more contributor license agreements.  See the NOTICE file
+#  distributed with this work for additional information
+#  regarding copyright ownership.  The ASF licenses this file
+#  to you under the Apache License, Version 2.0 (the
+#  "License"); you may not use this file except in compliance
+#  with the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+
+
+import os
+
+Test.Summary = 'Test TSEmergency API'
+Test.ContinueOnFail = True
+
+# Define default ATS
+ts = Test.MakeATSProcess('ts')
+
+Test.testName = 'Emergency Shutdown Test'
+
+ts.Disk.records_config.update({
+    'proxy.config.exec_thread.autoconfig': 0,
+    'proxy.config.exec_thread.autoconfig.scale': 1.5,
+    'proxy.config.exec_thread.limit': 16,
+    'proxy.config.accept_threads': 1,
+    'proxy.config.task_threads': 2,
+    'proxy.config.diags.debug.enabled': 1,
+    'proxy.config.diags.debug.tags': 'TSEmergency_test'
+})
+
+# Load plugin
+Test.PreparePlugin(os.path.join(Test.Variables.AtsTestToolsDir, 'plugins', 'emergency_shutdown.cc'), ts)
+
+# www.example.com Host
+tr = Test.AddTestRun()
+tr.Processes.Default.Command = 'printf "Emergency Shutdown Test"'
+tr.Processes.Default.ReturnCode = 0
+tr.Processes.Default.StartBefore(ts)
+ts.ReturnCode = 33
+ts.Ready = 0 # Need this to be 0 because we are testing shutdown, this is to make autest not think ats went away for a bad reason.
+ts.Streams.All = Testers.ExcludesExpression('failed to shutdown', 'should NOT contain "failed to shutdown"')
+ts.Disk.diags_log.Content = Testers.IncludesExpression('testing emergency shutdown', 'should contain "testing emergency shutdown"')
diff --git a/tests/gold_tests/shutdown/fatal.test.py b/tests/gold_tests/shutdown/fatal.test.py
new file mode 100644
index 0000000..6ba763d
--- /dev/null
+++ b/tests/gold_tests/shutdown/fatal.test.py
@@ -0,0 +1,51 @@
+'''
+'''
+#  Licensed to the Apache Software Foundation (ASF) under one
+#  or more contributor license agreements.  See the NOTICE file
+#  distributed with this work for additional information
+#  regarding copyright ownership.  The ASF licenses this file
+#  to you under the Apache License, Version 2.0 (the
+#  "License"); you may not use this file except in compliance
+#  with the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+
+
+import os
+
+Test.Summary = 'Test TSFatal API'
+Test.ContinueOnFail = True
+
+# Define default ATS
+ts = Test.MakeATSProcess('ts')
+
+Test.testName = 'Fatal Shutdown Test'
+
+ts.Disk.records_config.update({
+    'proxy.config.exec_thread.autoconfig': 0,
+    'proxy.config.exec_thread.autoconfig.scale': 1.5,
+    'proxy.config.exec_thread.limit': 16,
+    'proxy.config.accept_threads': 1,
+    'proxy.config.task_threads': 2,
+    'proxy.config.diags.debug.enabled': 1,
+    'proxy.config.diags.debug.tags': 'TSFatal_test'
+})
+
+# Load plugin
+Test.PreparePlugin(os.path.join(Test.Variables.AtsTestToolsDir, 'plugins', 'fatal_shutdown.cc'), ts)
+
+# www.example.com Host
+tr = Test.AddTestRun()
+tr.Processes.Default.Command = 'printf "Fatal Shutdown Test"'
+tr.Processes.Default.ReturnCode = 0
+tr.Processes.Default.StartBefore(ts)
+ts.ReturnCode = 70
+ts.Ready = 0 # Need this to be 0 because we are testing shutdown, this is to make autest not think ats went away for a bad reason.
+ts.Streams.All = Testers.ExcludesExpression('failed to shutdown', 'should NOT contain "failed to shutdown"')
+ts.Disk.diags_log.Content = Testers.IncludesExpression('testing fatal shutdown', 'should contain "testing fatal shutdown"')
diff --git a/tests/tools/plugins/emergency_shutdown.cc b/tests/tools/plugins/emergency_shutdown.cc
new file mode 100644
index 0000000..9957e40
--- /dev/null
+++ b/tests/tools/plugins/emergency_shutdown.cc
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <cstring>
+#include <stdlib.h> // for abort
+#include <ts/ts.h>  // for debug
+
+// debug messages viewable by setting 'proxy.config.diags.debug.tags'
+// in 'records.config'
+
+// debug messages during one-time initialization
+static const char DEBUG_TAG[] = "TSEmergency_test";
+
+// plugin registration info
+static char plugin_name[]   = "TSEmergency_test";
+static char vendor_name[]   = "apache";
+static char support_email[] = "duke8253@apache.org";
+
+static int
+test_handler(TSCont contp, TSEvent event, void *edata)
+{
+  TSDebug(DEBUG_TAG, "failed to shutdown");
+  return 0;
+}
+
+static int
+LifecycleHookTracer(TSCont contp, TSEvent event, void *edata)
+{
+  if (event == TS_EVENT_LIFECYCLE_TASK_THREADS_READY) {
+    TSCont contp = TSContCreate(test_handler, TSMutexCreate());
+    TSContScheduleOnPool(contp, 500, TS_THREAD_POOL_NET);
+    TSEmergency("testing emergency shutdown");
+  }
+  return 0;
+}
+
+void
+TSPluginInit(int argc, const char *argv[])
+{
+  TSPluginRegistrationInfo info;
+
+  info.plugin_name   = plugin_name;
+  info.vendor_name   = vendor_name;
+  info.support_email = support_email;
+
+  if (TSPluginRegister(&info) != TS_SUCCESS) {
+    TSEmergency("[%s] plugin registration failed", plugin_name);
+  }
+
+  TSLifecycleHookAdd(TS_LIFECYCLE_TASK_THREADS_READY_HOOK, TSContCreate(LifecycleHookTracer, TSMutexCreate()));
+}
diff --git a/tests/tools/plugins/fatal_shutdown.cc b/tests/tools/plugins/fatal_shutdown.cc
new file mode 100644
index 0000000..d749008
--- /dev/null
+++ b/tests/tools/plugins/fatal_shutdown.cc
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <cstring>
+#include <stdlib.h> // for abort
+#include <ts/ts.h>  // for debug
+
+// debug messages viewable by setting 'proxy.config.diags.debug.tags'
+// in 'records.config'
+
+// debug messages during one-time initialization
+static const char DEBUG_TAG[] = "TSFatal_test";
+
+// plugin registration info
+static char plugin_name[]   = "TSFatal_test";
+static char vendor_name[]   = "apache";
+static char support_email[] = "duke8253@apache.org";
+
+static int
+test_handler(TSCont contp, TSEvent event, void *edata)
+{
+  TSDebug(DEBUG_TAG, "failed to shutdown");
+  return 0;
+}
+
+static int
+LifecycleHookTracer(TSCont contp, TSEvent event, void *edata)
+{
+  if (event == TS_EVENT_LIFECYCLE_TASK_THREADS_READY) {
+    TSCont contp = TSContCreate(test_handler, TSMutexCreate());
+    TSContScheduleOnPool(contp, 500, TS_THREAD_POOL_NET);
+    TSFatal("testing fatal shutdown");
+  }
+  return 0;
+}
+
+void
+TSPluginInit(int argc, const char *argv[])
+{
+  TSPluginRegistrationInfo info;
+
+  info.plugin_name   = plugin_name;
+  info.vendor_name   = vendor_name;
+  info.support_email = support_email;
+
+  if (TSPluginRegister(&info) != TS_SUCCESS) {
+    TSEmergency("[%s] plugin registration failed", plugin_name);
+  }
+
+  TSLifecycleHookAdd(TS_LIFECYCLE_TASK_THREADS_READY_HOOK, TSContCreate(LifecycleHookTracer, TSMutexCreate()));
+}