faster & simpler solution for stream poll() - release

This commit is contained in:
Philippe G
2020-08-30 11:23:05 -07:00
parent 26d3d99738
commit 8e3fde6f6e

View File

@@ -46,27 +46,17 @@ struct buffer *streambuf = &buf;
#define UNLOCK mutex_unlock(streambuf->mutex) #define UNLOCK mutex_unlock(streambuf->mutex)
/* /*
After a lot of hesitation, I've added that "poll mutex" to prevent When LMS sends a close/open sequence very quickly, the stream thread might
socket from being allocated while we are still in poll(). The issue still be waiting in the poll() on the closed socket. It is never recommended
happens is we have a close quickly followed by an open, we might still to have a thread closing a socket used by another thread but it works, as
be in the poll() and simple OS fail as they re-allocate the same socket opposed to an infinite select().
on which a thread is still waiting. In stream_sock() a new socket is created and full OS will allocate a different
Ideally, you want to set the lock in the disconnect() but that would mean one but on RTOS and simple IP stack, the same might be re-used and that causes
very often we'd have to always wait for the end of the poll(), i.e. up to an exception as a thread is already waiting on a newly allocated socket
100ms for nothing most of the time where if it is in the open(), it is A simple variable that forces stream_sock() to wait until we are out of poll()
less elegant as closing a socket on which there is a poll() is not good is enough and much faster than a mutex
but it's more efficient as it is very rare that you'd have an open() less
then 100ms after a close()
*/ */
#if EMBEDDED static bool polling;
static mutex_type poll_mutex;
#define LOCK_L mutex_lock(poll_mutex)
#define UNLOCK_L mutex_unlock(poll_mutex)
#else
#define LOCK_L
#define UNLOCK_L
#endif
static sockfd fd; static sockfd fd;
struct streamstate stream; struct streamstate stream;
@@ -209,7 +199,7 @@ static void *stream_thread() {
} else { } else {
LOCK_L; polling = true;
pollinfo.fd = fd; pollinfo.fd = fd;
pollinfo.events = POLLIN; pollinfo.events = POLLIN;
if (stream.state == SEND_HEADERS) { if (stream.state == SEND_HEADERS) {
@@ -221,7 +211,7 @@ static void *stream_thread() {
if (_poll(ssl, &pollinfo, 100)) { if (_poll(ssl, &pollinfo, 100)) {
UNLOCK_L; polling = false;
LOCK; LOCK;
// check socket has not been closed while in poll // check socket has not been closed while in poll
@@ -374,7 +364,8 @@ static void *stream_thread() {
UNLOCK; UNLOCK;
} else { } else {
UNLOCK_L; // it is safe to set it unlocked
polling = false;
LOG_SDEBUG("poll timeout"); LOG_SDEBUG("poll timeout");
} }
} }
@@ -427,9 +418,6 @@ void stream_init(log_level level, unsigned stream_buf_size) {
*stream.header = '\0'; *stream.header = '\0';
fd = -1; fd = -1;
#if EMBEDDED
mutex_create_p(poll_mutex);
#endif
#if LINUX || FREEBSD #if LINUX || FREEBSD
touch_memory(streambuf->buf, streambuf->size); touch_memory(streambuf->buf, streambuf->size);
@@ -459,9 +447,6 @@ void stream_close(void) {
#endif #endif
free(stream.header); free(stream.header);
buf_destroy(streambuf); buf_destroy(streambuf);
#if EMBEDDED
mutex_destroy(poll_mutex);
#endif
} }
void stream_file(const char *header, size_t header_len, unsigned threshold) { void stream_file(const char *header, size_t header_len, unsigned threshold) {
@@ -503,9 +488,13 @@ void stream_file(const char *header, size_t header_len, unsigned threshold) {
void stream_sock(u32_t ip, u16_t port, const char *header, size_t header_len, unsigned threshold, bool cont_wait) { void stream_sock(u32_t ip, u16_t port, const char *header, size_t header_len, unsigned threshold, bool cont_wait) {
struct sockaddr_in addr; struct sockaddr_in addr;
LOCK_L; #if EMBEDDED
// wait till we are not polling anymore
for (LOCK; running && polling; UNLOCK, usleep(10000), LOCK);
UNLOCK;
#endif
int sock = socket(AF_INET, SOCK_STREAM, 0); int sock = socket(AF_INET, SOCK_STREAM, 0);
UNLOCK_L;
if (sock < 0) { if (sock < 0) {
LOG_ERROR("failed to create socket"); LOG_ERROR("failed to create socket");