Closed takagi closed 9 years ago
It looks that it's trying to stop an I/O watcher which is already freed. I have no idea why and I couldn't reproduce it on my MacBook.
I tried and could not reproduce the case.
ฅ*•ω•*ฅ < ros run -- --version
SBCL 1.2.11
ฅ*•ω•*ฅ < brew list libev
/usr/local/Cellar/libev/4.15/include/ (2 files)
/usr/local/Cellar/libev/4.15/lib/libev.4.dylib
/usr/local/Cellar/libev/4.15/lib/ (2 other files)
/usr/local/Cellar/libev/4.15/share/man/man3/ev.3
ฅ*•ω•*ฅ < uname -a
Darwin Tomoy-Air.local 14.3.0 Darwin Kernel Version 14.3.0: Mon Mar 23 11:59:05 PDT 2015; root:xnu-2782.20.48~5/RELEASE_X86_64 x86_64
I provide a further report and a probable cause.
Problem The following steps may reproduce the issue. Detailed behavior may differ for environments.
1.Run a Woo server on AWS of AMI ami-d05e75b8
.
> (ql:quickload :woo)
> (woo:run
(lambda (env)
(declare (ignore env))
'(200 (:content-type "text/plain") ("Hello, World"))))
2.Send the following incomplete HTTP request, intended to close the connection before Woo starting its response.
> (ql:quickload :usocket)
> (let* ((sock (usocket:socket-connect "127.0.0.1" 5000))
(s (usocket:socket-stream sock)))
(princ "GET / HTTP/1.1" s) (write-crlf s)
(princ "Host: localhost" s) (write-crlf s)
(usocket:socket-close sock))
where write-crlf
is:
(defun write-crlf (stream)
(write-char #\return stream)
(write-char #\linefeed stream))
3.After a few times sending, woo:run
returns with zero, that is not expected behavior.
> (woo:run
(lambda (env)
(declare (ignore env))
'(200 (:content-type "text/plain") ("Hello, World"))))
0
4.Run a Woo server again with woo:run
5.Sending the incomplete HTTP request again may cause memory fault.
Cause
It may caused by a write watcher ev-io
object not ev-io-init
ed is to be ev-io-stop
ed.
A write watcher ev-io
object seems to be ev-io-init
ed in init-write-io
, which is called in with-async-writing
macro after Woo has received a complete HTTP request to begin generating its response.
Before that, the write watcher ev-io
object is not initialized, happen to be ev-io-stop
ed when Woo gets EOF before receiving a complete HTTP request, causing memory fault on FFI.
Solution
It would help that initializing a write watcher when making a Woo socket in make-socket
. I guess it is not needed to delay initializing a write watcher after Woo is ready to start its response and init-write-io
is called. I will send a pull request for a patch later.
(defun make-socket (&rest initargs &key tcp-read-cb fd &allow-other-keys)
(let ((socket (apply #'%make-socket initargs)))
(lev:ev-io-init (socket-read-watcher socket)
tcp-read-cb
fd
lev:+EV-READ+)
+ (lev:ev-io-init (socket-write-watcher socket)
+ 'async-write-cb
+ fd
+ lev:+EV-WRITE+)
socket))
I think this has been fixed by #18.
Running a Woo server to benchmark with
wrk
tool causes memory fault on libev FFI. It happens towrk
more than once in my trials on OSX. I get similar condition on Ubuntu on Amazon EC2.REPL:
Shell:
Caused memory fault:
Environments
OSX:
Amazon EC2: