JUNNETWORKS / 42-webserv

Webserv is one of the projects in 42 cursus.
5 stars 0 forks source link

CGIが大量のデータを出力した後exitした時、EPOLLHUPでCGIからのデータ読み込みが止まり、クライアントに全データが送信されない #235

Closed JUNNETWORKS closed 2 years ago

JUNNETWORKS commented 2 years ago

以下のような toupper-cgi を作る

#!/bin/bash

# To permit this cgi, replace # on the first line above with the
# appropriate #!/path/to/sh shebang, and set this script executable
# with chmod 755.
#
# ***** !!! WARNING !!! *****
# This script echoes the server environment variables and therefore
# leaks information - so NEVER use it in a live server environment!
# It is provided only for testing purpose.
# Also note that it is subject to cross site scripting attacks on
# MS IE and any other browser which fails to honor RFC2616.

# disable filename globbing
set -f

echo "Content-type: text/plain; charset=iso-8859-1"
echo

INPUT=`cat`

echo TOUPPER
echo
echo input len ${#INPUT}
echo
echo ${INPUT^^}
echo

echo TOUPPER END

curl -X GET 127.0.0.1:49200/cgi-bin/toupper-cgi -d "$(python -c 'print("a" * 10000)')" のように送ると、EPOLLHUP が発生し、クライアントに全データを送信する前にTCPソケットを閉じてしまう。

原因はCGIがexitしたときに、UnixDomainSocketを閉じる。このときに EPOLLHUP が発生するのだが、これは read() で0が返ってくるまで読み込むことで解決できる。

EPOLLHUP Hang up happened on the associated file descriptor.

epoll_wait(2) will always wait for this event; it is not necessary to set it in events when calling epoll_ctl().

Note that when reading from a channel such as a pipe or a stream socket, this event merely indicates that the peer closed its end of the channel. Subsequent reads from the channel will return 0 (end of file) only after all outstanding data in the channel has been consumed.

man epoll