You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by da...@apache.org on 2020/01/06 19:18:30 UTC

[couchdb] 01/01: Make all OOM errors fatal in couchjs

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

davisp pushed a commit to branch couchjs-oom-errors-are-fatal
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit fbe262afe289b4e0e4e952241baf533a3f7241f9
Author: Paul J. Davis <pa...@gmail.com>
AuthorDate: Mon Jan 6 11:06:40 2020 -0600

    Make all OOM errors fatal in couchjs
---
 src/couch/priv/couch_js/60/main.cpp     |  1 +
 src/couch/priv/couch_js/60/util.cpp     |  8 ++++++
 src/couch/priv/couch_js/60/util.h       |  1 +
 src/couch/test/eunit/couch_js_tests.erl | 45 +++++++++++++++++++++++++++++++++
 test/javascript/tests/view_errors.js    |  4 +--
 5 files changed, 57 insertions(+), 2 deletions(-)

diff --git a/src/couch/priv/couch_js/60/main.cpp b/src/couch/priv/couch_js/60/main.cpp
index ecedfbd..0486722 100644
--- a/src/couch/priv/couch_js/60/main.cpp
+++ b/src/couch/priv/couch_js/60/main.cpp
@@ -420,6 +420,7 @@ main(int argc, const char* argv[])
         return 1;
 
     JS::SetWarningReporter(cx, couch_error);
+    JS::SetOutOfMemoryCallback(cx, couch_handle_oom, NULL);
     JS_SetContextPrivate(cx, args);
     JS_SetSecurityCallbacks(cx, &security_callbacks);
 
diff --git a/src/couch/priv/couch_js/60/util.cpp b/src/couch/priv/couch_js/60/util.cpp
index 894b425..bba342d 100644
--- a/src/couch/priv/couch_js/60/util.cpp
+++ b/src/couch/priv/couch_js/60/util.cpp
@@ -309,6 +309,14 @@ couch_error(JSContext* cx, JSErrorReport* report)
 }
 
 
+void
+couch_handle_oom(JSContext* cx, void* data)
+{
+    fprintf(stdout, "[\"fatal\",\"oom\",\"out of memory\"]\n");
+    exit(37);
+}
+
+
 bool
 couch_load_funcs(JSContext* cx, JS::HandleObject obj, JSFunctionSpec* funcs)
 {
diff --git a/src/couch/priv/couch_js/60/util.h b/src/couch/priv/couch_js/60/util.h
index 45caa34..50f9af7 100644
--- a/src/couch/priv/couch_js/60/util.h
+++ b/src/couch/priv/couch_js/60/util.h
@@ -35,6 +35,7 @@ JSString* couch_readline(JSContext* cx, FILE* fp);
 size_t couch_readfile(const char* file, char** outbuf_p);
 void couch_print(JSContext* cx, unsigned int argc, JS::CallArgs argv);
 void couch_error(JSContext* cx, JSErrorReport* report);
+void couch_handle_oom(JSContext* cx, void* data);
 bool couch_load_funcs(JSContext* cx, JS::HandleObject obj, JSFunctionSpec* funcs);
 
 
diff --git a/src/couch/test/eunit/couch_js_tests.erl b/src/couch/test/eunit/couch_js_tests.erl
new file mode 100644
index 0000000..0585a33
--- /dev/null
+++ b/src/couch/test/eunit/couch_js_tests.erl
@@ -0,0 +1,45 @@
+% Licensed 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.
+
+-module(couch_js_tests).
+-include_lib("eunit/include/eunit.hrl").
+
+
+-define(FUNC, <<
+  "function(doc) {\n"
+  "  var val = \"0123456789ABCDEF\";\n"
+  "  while(true) {emit(val, val);}\n"
+  "}\n"
+>>).
+
+
+couch_js_test_() ->
+    {
+        "Test couchjs",
+        {
+            setup,
+            fun test_util:start_couch/0,
+            fun test_util:stop_couch/1,
+            [
+                fun should_recover_from_oom/0
+            ]
+        }
+    }.
+
+
+should_recover_from_oom() ->
+    Proc = couch_query_servers:get_os_process(<<"javascript">>),
+    true = couch_query_servers:proc_prompt(Proc, [<<"add_fun">>, ?FUNC]),
+    ?assertThrow(
+        {<<"oom">>, <<"out of memory">>},
+        couch_query_servers:proc_prompt(Proc, [<<"map_doc">>, <<"{}">>])
+    ).
diff --git a/test/javascript/tests/view_errors.js b/test/javascript/tests/view_errors.js
index 7577b80..43db3c8 100644
--- a/test/javascript/tests/view_errors.js
+++ b/test/javascript/tests/view_errors.js
@@ -145,7 +145,7 @@ couchTests.view_errors = function(debug) {
         _id:"_design/infinite",
         language: "javascript",
         views: {
-          "infinite_loop" :{map:"function(doc) {while(true){emit(doc,doc);}};"}
+          "infinite_loop" :{map:"function(doc) {while(true){};}"}
         }
       };
       T(db.save(designDoc3).ok);
@@ -154,7 +154,7 @@ couchTests.view_errors = function(debug) {
           db.view("infinite/infinite_loop");
           T(0 == 1);
       } catch(e) {
-          T(e.error == "os_process_error" || e.error == "unnamed_error");
+          T(e.error == "os_process_error");
       }
 
       // Check error responses for invalid multi-get bodies.