FDH2 / UxPlay

AirPlay Unix mirroring server
GNU General Public License v3.0
1.34k stars 72 forks source link

cpu 100%,dead loop。 #222

Closed CNoob4ever closed 8 months ago

CNoob4ever commented 9 months ago

image image image

fduncanh commented 9 months ago

give details. (about the computer and the OS, uxplay version etc, self-compiled or from a distribution?)

Why did you show the code in the top screen, did you get such a timeout?

I have no idea why llhttp acted strange.

Is this reproducible or a one-time event?

If you can reproduce it, please do it with the uxplay -d (debug) option and post the output here as a "*.txt>" file

CNoob4ever commented 9 months ago

give details. (about the computer and the OS, uxplay version etc, self-compiled or from a distribution?)

Why did you show the code in the top screen, did you get such a timeout?

I have no idea why llhttp acted strange.

Is this reproducible or a one-time event?

If you can reproduce it, please do it with the uxplay -d (debug) option and post the output here as a "*.txt>" file

Hi, I have done secondary development based on uxplay. The setup includes an N100 mini host, Ubuntu 22.04, and uxplay version 1.64. When connecting and disconnecting AirPlay frequently, there is a chance of triggering a conn_reset, which leads to a probabilistic loop in the s_n_llhttpinternaln_closed function within the llhttp__internal_run process. Currently, my solution is to use the macro LLHTTP_STRICT_MODE=1 to address the issue.

fduncanh commented 9 months ago

Is this a llhttp bug?

There is also a possibilty of an unclean socket after a reset, it might be the issue.

you can help uxplay by diagnosing this more to fix any issue in the code.

CNoob4ever commented 9 months ago

Is this a llhttp bug?

  • Try replacing the contents of the lib/llhttp directory with llhttp v6.0.7 (find it in a github version of UxPlay dated before 2022.10.29
  • is it a uxplay bug? (in the conn_reset code, a reset should shut down processes involving http parsing (which is what llhttp does)
  • can it be reliably reproduced by triggering a conn_reset? (just shut down the wifi on the client, and a "normal" reset will occur after 15 secs.)

There is also a possibilty of an unclean socket after a reset, it might be the issue.

  • should llhttp be running with LLHTTP_STRICT_MODE=1 anyway?

you can help uxplay by diagnosing this more to fix any issue in the code.

I believe this is a bug. I have looked at several versions of llhttp on GitHub, and in s_n_llhttpinternaln_closed, there is no infinite loop. I have added LLHTTP_STRICT_MODE=1 to the compiler, and in the past few days of testing, I haven't encountered any issues.

fduncanh commented 9 months ago

I believe this is a bug. I have looked at several versions of llhttp on GitHub, and in s_n_llhttpinternaln_closed, there is no infinite loop. I have added LLHTTP_STRICT_MODE=1 to the compiler, and in the past few days of testing, I haven't encountered any issues.

CNoob4ever commented 9 months ago
  • as opposed to a bug in llht

There is a bug in llhttp used by uxplay. I have added the macro definition LLHTTP_STRICT_MODE=1 in CMAKE. Currently, I see that the portion around line 10594 in master/lib/llhttp/llhttp.c is causing an infinite loop. image

fduncanh commented 9 months ago

Thanks for your investigations. I would like to try to make a bug report to llhttp.

To help with this I have made two new branches of UxPlay on github:

can you test these (without STRICT_MODE changes) to see if both , either, or none of these show the bug you see.

Thanks!

mkdir llhttp605
cd llhttp605
git clone http://github.com/FDH2/UxPlay
cd UxPlay
git checkout llhttp605
mkdir build
cd build
cmake ..
make

then run ./uxplay

repeat for llhttp912 in the other directory.

fduncanh commented 9 months ago
grep  llhttp *

http_request.c:#include "llhttp/llhttp.h"
http_request.c:    llhttp_t parser;
http_request.c:    llhttp_settings_t parser_settings;
http_request.c:on_url(llhttp_t *parser, const char *at, size_t length)
http_request.c:on_header_field(llhttp_t *parser, const char *at, size_t length)
http_request.c:on_header_value(llhttp_t *parser, const char *at, size_t length)
http_request.c:on_body(llhttp_t *parser, const char *at, size_t length)
http_request.c:on_message_complete(llhttp_t *parser)
http_request.c:    request->method = llhttp_method_name(request->parser.method);
http_request.c:    llhttp_settings_init(&request->parser_settings);
http_request.c:    llhttp_init(&request->parser, HTTP_REQUEST, &request->parser_settings);
http_request.c:    ret = llhttp_execute(&request->parser,
http_request.c:    return (llhttp_get_errno(&request->parser) != HPE_OK);
http_request.c:    return llhttp_errno_name(llhttp_get_errno(&request->parser));
http_request.c:    return llhttp_get_error_reason(&request->parser);

pairing:http_request.c:    request->method = llhttp_method_name(request->parser.method);
pairing:http_request.c:    llhttp_settings_init(&request->parser_settings);
pairing:http_request.c:    llhttp_init(&request->parser, HTTP_REQUEST, &request->parser_settings);
pairing:http_request.c:    ret = llhttp_execute(&request->parser,
pairing:http_request.c:    return (llhttp_get_errno(&request->parser) != HPE_OK);
pairing:http_request.c:    return llhttp_errno_name(llhttp_get_errno(&request->parser));
pairing:http_request.c:    return llhttp_get_error_reason(&request->parser);

is there any way you can identify which call is involved?

fduncanh commented 9 months ago

@CNoob4ever

Hi, I have done secondary development based on uxplay. The setup includes an N100 mini host, Ubuntu 22.04, and uxplay version 1.64. When connecting and disconnecting AirPlay frequently, there is a chance of triggering a conn_reset, which leads to a probabilistic loop in the s_n_llhttpinternaln_closed function within the llhttp__internal_run process. Currently, my solution is to use the macro LLHTTP_STRICT_MODE=1 to address the issue.

I see that conn_reset (in uxplay.cpp) calls raop_stop (in lib/raop.c) which calls httpd_stop ( in lib/httpd.c)

maybe simply changing raop_stop so it calls httpd_destroy rather than http_stop will fix your issue, without LLHTTP_STRICT=1 (just edit "https_stop" to "httpd_destroy")

can you test?

EDIT: calling httpd_destroy caused a segfault. But I am wondering whether this issue would be fixed in uxplay by ensuring all sockets are properly closed when conn_reset is called.

fduncanh commented 9 months ago

@CNoob4ever

any more details are welcomed here

fduncanh commented 8 months ago

closed, (will reopen if more into is provided) can't duplicate