node.native
node.native copied to clipboard
Segmentation fault when concurrent requests arrives.
with a single connection and many requests, there is no problem. but I send multiply requests concurrently, segmentation fault occurs ( line 336 in http.h ).
how to produce the error :
ab -k -n 50000 -c 100 -t 20 http://localhost:8080/ This is ApacheBench, Version 2.3 <$Revision: 1430300 $> Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking localhost (be patient) apr_socket_recv: Connection reset by peer (104) Total of 14 requests completed
full Stack trace from gdb :
(gdb) bt full #0 0x00000000004089a7 in native::http::client_context::~client_context()::{lambda()#1}::operator()() const () at ./native/http.h:336
std::__ioinit = {static _S_refcount = <optimized out>,
static _S_synced_with_stdio = <optimized out>}
#1 0x000000000040c473 in std::_Function_handler<void (), native::http::client_context::~client_context()::{lambda()#1}>::_M_invoke(std::_Any_data const&) (
__functor=...) at /usr/include/c++/4.8/functional:2071
No locals. #2 0x000000000040d112 in std::function<void ()>::operator()() const (
this=0x642750) at /usr/include/c++/4.8/functional:2464
No locals. #3 0x000000000040b60a in native::internal::callback_object<std::function<void ()> >::invoke<>() (this=0x642740) at ./native/callback.h:46
No locals. #4 0x00000000004098ef in native::callbacks::invoke<std::function<void ()>>(void*, int) (target=0x642550, cid=0) at ./native/callback.h:84
__PRETTY_FUNCTION__ = "static typename std::result_of<_Functor(_ArgTypes ...)>::type native::callbacks::invoke(void*, int, A&& ...) [with callback_t = std::function<void()>; A = {}; typename std::result_of<_Functor(_ArgType"...
x = 0x642740
#5 0x00000000004067db in native::base::handle::close(std::function<void ()>)::{lambda(uv_handle_s_)#1}::operator()(uv_handle_s_) const (__closure=0x0,
with this modification, error disappears :
if(socket_)
{
// TODO: maybe close() does not affect socket_ pointer itself. So, delete socket_ does not have to be inside the callback.
socket_->close([=](){
//delete socket_;
//socket_ = nullptr;
});
delete socket_;
}
benchmark result after modification :
monfared@monfared-ubuntu:~/node.native$ ab -k -n 800000 -c 300 http://localhost:8080/ This is ApacheBench, Version 2.3 <$Revision: 1430300 $> Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking localhost (be patient) Completed 80000 requests Completed 160000 requests Completed 240000 requests Completed 320000 requests Completed 400000 requests Completed 480000 requests Completed 560000 requests Completed 640000 requests Completed 720000 requests Completed 800000 requests Finished 800000 requests
Server Software:
Server Hostname: localhost
Server Port: 8080
Document Path: / Document Length: 8 bytes
Concurrency Level: 300 Time taken for tests: 20.055 seconds Complete requests: 800000 Failed requests: 0 Write errors: 0 Keep-Alive requests: 0 Total transferred: 57600000 bytes HTML transferred: 6400000 bytes Requests per second: 39890.78 #/sec Time per request: 7.521 ms Time per request: 0.025 [ms](mean, across all concurrent requests) Transfer rate: 2804.82 [Kbytes/sec] received
Connection Times (ms) min mean[+/-sd] median max Connect: 0 1 6.4 0 1000 Processing: 1 3 0.4 3 9 Waiting: 1 3 0.6 3 7 Total: 2 4 6.4 4 1004
Percentage of the requests served within a certain time (ms) 50% 4 66% 4 75% 4 80% 4 90% 4 95% 4 98% 4 99% 6 100% 1004 (longest request)
It's strange this problem. As far as I can see, the news & deletes match up for the socket objects. The same regions of memory are being allocated, deleted and reallocated to hold sockets, but it naively looks like they're doing the right thing. I'm going to try out std::unique_ptr as a solution; see if that works.
@hmonfared - take a look at my pull request to see my resolution for this problem.
Hi, Thanks, It worked fine, except that the performance was dropped about 1000 transactions per second comparing with my modified version. I got following result with same benchmarking options: Total transferred: 57600000 bytes HTML transferred: 6400000 bytes Requests per second: 38703.70 #/sec Time per request: 7.751 ms Time per request: 0.026 [ms](mean, across all concurrent requests) Transfer rate: 2721.35 [Kbytes/sec] received maybe it is because of shared_ptr overhead. Regards Hassan H. Monfared
Hi @hmonfared - yes the additional processing time in the shared_ptr code, plus actually calling free() for every connection. This is unavoidable, I think.
Hi @sebjameswml , thanks for the reply. of course shared_ptr is faile-safe, but can't you call 'delete' operator explicitly as I did ? : if(socket_) { socket_->close(={}); delete socket_; }
Hi Hassan, sorry - I missed your bit of code - I mis-read it as simply commenting out the existing code.