From cacc199432d81658fbb46ddc9ba52be38eea9a7d Mon Sep 17 00:00:00 2001
From: Bruce Toll <btoll@dhsus.com>
Date: Mon, 11 Mar 2019 11:32:10 -0400
Subject: [PATCH] Modified hello example for test of webrequest leak

Also includes wt_config.xml for testing with relevant debug outputs
enabled and wt_config_less_debug.xml for less output.

To see complete debug output, need to build DEBUG version of wt with
DEBUG logging option. NOTE: Also built specifying WT_DEBUG_JS.

Debug output will be buffered to memory to improve the likelihood
of capturing the race condition under test. To flush output, the
hello.wt application needs to be killed. If using "tee" to capture
the output, it should be killed from another session to avoid
losing the output.

This commit also includes upgrading a WtReply.C busy LOG_DEBUG to
LOG_INFO, as it is fairly important to understanding this issue.
---
 examples/hello/hello.C                  | 97 ++++++++++++++++++++++++-
 examples/hello/wt_config.xml            | 10 +++
 examples/hello/wt_config_less_debug.xml | 10 +++
 src/http/WtReply.C                      |  2 +-
 4 files changed, 117 insertions(+), 2 deletions(-)
 create mode 100644 examples/hello/wt_config.xml
 create mode 100644 examples/hello/wt_config_less_debug.xml

diff --git a/examples/hello/hello.C b/examples/hello/hello.C
index 97f64335..33c8e126 100644
--- a/examples/hello/hello.C
+++ b/examples/hello/hello.C
@@ -6,11 +6,24 @@
 
 #include <Wt/WApplication.h>
 #include <Wt/WBreak.h>
+#include <Wt/WDialog.h>
 #include <Wt/WContainerWidget.h>
 #include <Wt/WLineEdit.h>
 #include <Wt/WPushButton.h>
+#include <Wt/WServer.h>
+#include <Wt/WTimer.h>
 #include <Wt/WText.h>
 
+#if !defined(WT_WIN32)
+#include <signal.h>
+#endif
+
+#define STRSTREAM_LOG
+#if defined(STRSTREAM_LOG)
+#include <sstream>
+#endif
+
+
 /*
  * A simple hello world application class which demonstrates how to react
  * to events, read input, and give feed-back.
@@ -23,8 +36,10 @@ public:
 private:
   Wt::WLineEdit *nameEdit_;
   Wt::WText     *greeting_;
+  Wt::Core::observing_ptr<Wt::WDialog> idleTimeoutDialog_;
 
   void greet();
+  void idleTimeout() override;
 };
 
 /*
@@ -79,6 +94,86 @@ void HelloApplication::greet()
   greeting_->setText("Hello there, " + nameEdit_->text());
 }
 
+void HelloApplication::idleTimeout()
+{
+  log("info") << "HelloApplication: idleTimeout() called";
+  if (idleTimeoutDialog_)
+    return; // Prevent multiple dialogs
+
+  log("info") << "HelloApplication: idleTimeout() about to show dialog";
+
+  idleTimeoutDialog_ = addChild(Wt::cpp14::make_unique<Wt::WDialog>("Idle timeout"));
+  idleTimeoutDialog_->contents()->addNew<Wt::WText>("This session has timed-out, "
+                                                    "press 'restart' to continue using the application");
+  auto btn = idleTimeoutDialog_->footer()->addNew<Wt::WPushButton>("restart");
+  btn->setLink(bookmarkUrl());
+  btn->setFocus();
+  idleTimeoutDialog_->show();
+  quit();
+}
+
+#if defined(STRSTREAM_LOG)
+class BufferLog {
+public:
+  ~BufferLog() {
+    ss_ << std::ends;
+    std::cerr << ss_.str() << std::endl;
+  }
+  void setup() {
+    Wt::logInstance().setStream(ss_);
+  };
+
+private:
+  std::ostringstream ss_;
+};
+#endif
+
+int WRun(int argc, char *argv[], Wt::ApplicationCreator createApplication)
+{
+  // insure buffered log contents are sent to stderr on exit
+  BufferLog bufferLog;
+
+  try {
+    Wt::WServer server(argv[0], "");
+    try {
+      server.setServerConfiguration(argc, argv, WTHTTP_CONFIGURATION);
+
+      // override the default log output established in setServerConfiguration
+      bufferLog.setup();
+
+      server.addEntryPoint(Wt::EntryPointType::Application, createApplication);
+      if (server.start()) {
+#ifdef WT_THREADED
+        // MacOSX + valgrind:
+        // for (;;) { sleep(100); }
+        int sig = Wt::WServer::waitForShutdown();
+        Wt::log("info") << "shutdown (signal = " << sig << ")";
+#endif
+        server.stop();
+
+#ifdef WT_THREADED
+#ifndef WT_WIN32
+        if (sig == SIGHUP)
+          // Mac OSX: _NSGetEnviron()
+          Wt::WServer::restart(argc, argv, nullptr);
+#endif // WIN32
+#endif // WT_THREADED
+      }
+
+      return 0;
+    } catch (std::exception& e) {
+      Wt::log("error") << "fatal: " << e.what();
+      return 1;
+    }
+  } catch (Wt::WServer::Exception& e) {
+    Wt::log("error") << "fatal: " << e.what();
+    return 1;
+  } catch (std::exception& e) {
+    Wt::log("error") << "fatal: " << e.what();
+    return 1;
+  }
+}
+
 int main(int argc, char **argv)
 {
   /*
@@ -92,7 +187,7 @@ int main(int argc, char **argv)
    * support. The function should return a newly instantiated application
    * object.
    */
-  return Wt::WRun(argc, argv, [](const Wt::WEnvironment &env) {
+  return WRun(argc, argv, [](const Wt::WEnvironment &env) {
     /*
      * You could read information from the environment to decide whether
      * the user has permission to start a new application
diff --git a/examples/hello/wt_config.xml b/examples/hello/wt_config.xml
new file mode 100644
index 00000000..c6bc8ca0
--- /dev/null
+++ b/examples/hello/wt_config.xml
@@ -0,0 +1,10 @@
+<server>
+    <application-settings location="*">
+        <session-management>
+            <timeout>90</timeout>
+            <idle-timeout>120</idle-timeout>
+        </session-management>
+        <log-config>* -debug debug:websession debug:wthttp debug:wthttp/async</log-config>
+        <web-sockets>true</web-sockets>
+    </application-settings>
+</server>
diff --git a/examples/hello/wt_config_less_debug.xml b/examples/hello/wt_config_less_debug.xml
new file mode 100644
index 00000000..fa54f0c9
--- /dev/null
+++ b/examples/hello/wt_config_less_debug.xml
@@ -0,0 +1,10 @@
+<server>
+    <application-settings location="*">
+        <session-management>
+            <timeout>90</timeout>
+            <idle-timeout>120</idle-timeout>
+        </session-management>
+        <log-config>* -debug</log-config>
+        <web-sockets>true</web-sockets>
+    </application-settings>
+</server>
diff --git a/src/http/WtReply.C b/src/http/WtReply.C
index 043ee84b..ed04f8d9 100644
--- a/src/http/WtReply.C
+++ b/src/http/WtReply.C
@@ -451,7 +451,7 @@ void WtReply::send(const Wt::WebRequest::WriteCallback& callBack,
   fetchMoreDataCallback_ = callBack;
 
   if (sending_ != 0) {
-    LOG_DEBUG("WtReply::send(): still busy sending... ignoring");
+    LOG_INFO("WtReply::send(): still busy sending... ignoring");
     return;
   }
 
-- 
2.18.1

