From e573d98e487d1df6a81680b3b3113465b3edae40 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Dominik=20Tomic=CC=8Cevic=CC=81?=
 <dominik.tomicevic@gmail.com>
Date: Sat, 19 Mar 2016 12:39:30 +0100
Subject: [PATCH] hacked uv_async_send SIGSEGV bug

---
 Makefile               |  2 +-
 demo/worker/client.cpp | 28 ++++++++++++++--------------
 memgraph.cpp           | 15 +++++++++++----
 threading/pool.hpp     |  2 +-
 threading/task.hpp     | 36 +++++++++++++++++-------------------
 5 files changed, 44 insertions(+), 39 deletions(-)

diff --git a/Makefile b/Makefile
index 4f2e5879d..722d3ab2b 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
 CXX=clang++
-CFLAGS=-std=c++1y -O2 -Wall -Wno-unknown-pragmas
+CFLAGS=-std=c++1y -DNDEBUG -O2 -Wall -Wno-unknown-pragmas
 CFLAGS_DEBUG=-std=c++1y -Wall -Wno-unknown-pragmas -g
 LDFLAGS=-luv -lhttp_parser speedy/r3/.libs/libr3.a -L/usr/local/lib -lpcre -pthread
 
diff --git a/demo/worker/client.cpp b/demo/worker/client.cpp
index 4472e6610..33453f9bb 100644
--- a/demo/worker/client.cpp
+++ b/demo/worker/client.cpp
@@ -25,22 +25,22 @@ int main(int argc, char* argv[])
     auto duration    = std::stod(argv[4]);
 
     // memgraph
-    //std::vector<std::string> queries {
-    //    "CREATE (n{id:@}) RETURN n",
-    //    "MATCH (n{id:#}),(m{id:#}) CREATE (n)-[r:test]->(m) RETURN r",
-    //    "MATCH (n{id:#}) SET n.prop = ^ RETURN n",
-    //    "MATCH (n{id:#}) RETURN n",
-    //    "MATCH (n{id:#})-[r]->(m) RETURN count(r)"
-    //};
+    std::vector<std::string> queries {
+        "CREATE (n{id:@}) RETURN n",
+        "MATCH (n{id:#}),(m{id:#}) CREATE (n)-[r:test]->(m) RETURN r",
+        "MATCH (n{id:#}) SET n.prop = ^ RETURN n",
+        "MATCH (n{id:#}) RETURN n",
+        "MATCH (n{id:#})-[r]->(m) RETURN count(r)"
+    };
 
     // neo4j
-    std::vector<std::string> queries {
-        "CREATE (n:Item{id:@}) RETURN n",
-        "MATCH (n:Item{id:#}),(m:Item{id:#}) CREATE (n)-[r:test]->(m) RETURN r",
-        "MATCH (n:Item{id:#}) SET n.prop = ^ RETURN n",
-        "MATCH (n:Item{id:#}) RETURN n",
-        "MATCH (n:Item{id:#})-[r]->(m) RETURN count(r)"
-    };
+    /* std::vector<std::string> queries { */
+    /*     "CREATE (n:Item{id:@}) RETURN n", */
+    /*     "MATCH (n:Item{id:#}),(m:Item{id:#}) CREATE (n)-[r:test]->(m) RETURN r", */
+    /*     "MATCH (n:Item{id:#}) SET n.prop = ^ RETURN n", */
+    /*     "MATCH (n:Item{id:#}) RETURN n", */
+    /*     "MATCH (n:Item{id:#})-[r]->(m) RETURN count(r)" */
+    /* }; */
 
     auto threads = queries.size();
 
diff --git a/memgraph.cpp b/memgraph.cpp
index db3689edf..0dba9ef7e 100644
--- a/memgraph.cpp
+++ b/memgraph.cpp
@@ -14,8 +14,16 @@
 
 #include "utils/terminate_handler.hpp"
 
-int main()
+int main(int argc, char* argv[])
 {
+    if(argc < 2)
+    {
+        std::cout << "Port not defined" << std::endl;
+        std::exit(0);
+    }
+
+    auto port = std::stoi(argv[1]);
+
     std::set_terminate(&terminate_handler);
 
     ioc::Container container;
@@ -25,12 +33,11 @@ int main()
     auto loop = container.singleton<uv::UvLoop>();
 
     auto app = container.singleton<sp::Speedy, uv::UvLoop>("/db/data");
-    container.singleton<Pool>(4);
-    container.singleton<Task, uv::UvLoop, Pool>();
+    container.singleton<Task, uv::UvLoop>();
 
     init(container);
 
-    http::Ipv4 ip("0.0.0.0", 7474);
+    http::Ipv4 ip("0.0.0.0", port);
     app->listen(ip);
 
     loop->run(uv::UvLoop::Mode::Default);
diff --git a/threading/pool.hpp b/threading/pool.hpp
index f2b062816..4cd923222 100644
--- a/threading/pool.hpp
+++ b/threading/pool.hpp
@@ -24,7 +24,7 @@ public:
 
     Pool(Pool&) = delete;
     Pool(Pool&&) = delete;
-    
+
     ~Pool()
     {
         alive.store(false, std::memory_order_release);
diff --git a/threading/task.hpp b/threading/task.hpp
index 2c96235e5..4d77c1b37 100644
--- a/threading/task.hpp
+++ b/threading/task.hpp
@@ -18,18 +18,15 @@ class Task
     struct Work
     {
 
-        Work(uv::UvLoop& loop, work_t<T> work, after_work_t<T> after_work)
+        Work(work_t<T> work, after_work_t<T> after_work)
             : work(std::move(work)), after_work(std::move(after_work))
         {
-            uv_async_init(loop, &this->async, async_cb);
+            req.data = static_cast<void*>(this);
         }
 
         void operator()()
         {
             result.set(std::move(work()));
-
-            async.data = static_cast<void*>(this);
-            uv_async_send(&this->async);
         }
 
         work_t<T> work;
@@ -37,28 +34,28 @@ class Task
 
         Placeholder<T> result;
 
-        uv_async_t async;
+        uv_work_t req;
 
-    private:
-        static void async_cb(uv_async_t* handle)
+        static void work_cb(uv_work_t* req)
         {
-            auto work = static_cast<Work<T>*>(handle->data);
+            auto& work = *static_cast<Work<T>*>(req->data);
+            work();
+        }
+
+        static void after_work_cb(uv_work_t* req, int)
+        {
+            auto work = static_cast<Work<T>*>(req->data);
 
             work->after_work(std::move(work->result.get()));
 
-            auto async_as_handle = reinterpret_cast<uv_handle_t*>(handle);
-
-            uv_close(async_as_handle, [](uv_handle_t* handle) {
-                auto work = static_cast<Work<T>*>(handle->data);
-                delete work;
-            });
+            delete work;
         }
     };
 
 public:
     using sptr = std::shared_ptr<Task>;
 
-    Task(uv::UvLoop::sptr loop, Pool::sptr pool) : loop(loop), pool(pool) {}
+    Task(uv::UvLoop::sptr loop) : loop(loop) {}
 
     Task(Task&) = delete;
     Task(Task&&) = delete;
@@ -68,13 +65,14 @@ public:
     {
         using T = decltype(work());
 
-        auto w = new Work<T>(*loop, std::forward<F1>(work),
+        auto w = new Work<T>(std::forward<F1>(work),
                              std::forward<F2>(after_work));
 
-        pool->run([w]() { w->operator()(); });
+        uv_queue_work(*loop, &w->req,
+                      Work<T>::work_cb,
+                      Work<T>::after_work_cb);
     }
 
 private:
     uv::UvLoop::sptr loop;
-    Pool::sptr pool;
 };