mirror of
https://github.com/sle118/squeezelite-esp32.git
synced 2025-12-09 21:17:18 +03:00
faster & simpler solution for stream poll() - release
This commit is contained in:
@@ -46,27 +46,17 @@ struct buffer *streambuf = &buf;
|
||||
#define UNLOCK mutex_unlock(streambuf->mutex)
|
||||
|
||||
/*
|
||||
After a lot of hesitation, I've added that "poll mutex" to prevent
|
||||
socket from being allocated while we are still in poll(). The issue
|
||||
happens is we have a close quickly followed by an open, we might still
|
||||
be in the poll() and simple OS fail as they re-allocate the same socket
|
||||
on which a thread is still waiting.
|
||||
Ideally, you want to set the lock in the disconnect() but that would mean
|
||||
very often we'd have to always wait for the end of the poll(), i.e. up to
|
||||
100ms for nothing most of the time where if it is in the open(), it is
|
||||
less elegant as closing a socket on which there is a poll() is not good
|
||||
but it's more efficient as it is very rare that you'd have an open() less
|
||||
then 100ms after a close()
|
||||
When LMS sends a close/open sequence very quickly, the stream thread might
|
||||
still be waiting in the poll() on the closed socket. It is never recommended
|
||||
to have a thread closing a socket used by another thread but it works, as
|
||||
opposed to an infinite select().
|
||||
In stream_sock() a new socket is created and full OS will allocate a different
|
||||
one but on RTOS and simple IP stack, the same might be re-used and that causes
|
||||
an exception as a thread is already waiting on a newly allocated socket
|
||||
A simple variable that forces stream_sock() to wait until we are out of poll()
|
||||
is enough and much faster than a mutex
|
||||
*/
|
||||
#if EMBEDDED
|
||||
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 bool polling;
|
||||
static sockfd fd;
|
||||
|
||||
struct streamstate stream;
|
||||
@@ -209,7 +199,7 @@ static void *stream_thread() {
|
||||
|
||||
} else {
|
||||
|
||||
LOCK_L;
|
||||
polling = true;
|
||||
pollinfo.fd = fd;
|
||||
pollinfo.events = POLLIN;
|
||||
if (stream.state == SEND_HEADERS) {
|
||||
@@ -221,7 +211,7 @@ static void *stream_thread() {
|
||||
|
||||
if (_poll(ssl, &pollinfo, 100)) {
|
||||
|
||||
UNLOCK_L;
|
||||
polling = false;
|
||||
LOCK;
|
||||
|
||||
// check socket has not been closed while in poll
|
||||
@@ -374,7 +364,8 @@ static void *stream_thread() {
|
||||
UNLOCK;
|
||||
|
||||
} else {
|
||||
UNLOCK_L;
|
||||
// it is safe to set it unlocked
|
||||
polling = false;
|
||||
LOG_SDEBUG("poll timeout");
|
||||
}
|
||||
}
|
||||
@@ -427,9 +418,6 @@ void stream_init(log_level level, unsigned stream_buf_size) {
|
||||
*stream.header = '\0';
|
||||
|
||||
fd = -1;
|
||||
#if EMBEDDED
|
||||
mutex_create_p(poll_mutex);
|
||||
#endif
|
||||
|
||||
#if LINUX || FREEBSD
|
||||
touch_memory(streambuf->buf, streambuf->size);
|
||||
@@ -459,9 +447,6 @@ void stream_close(void) {
|
||||
#endif
|
||||
free(stream.header);
|
||||
buf_destroy(streambuf);
|
||||
#if EMBEDDED
|
||||
mutex_destroy(poll_mutex);
|
||||
#endif
|
||||
}
|
||||
|
||||
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) {
|
||||
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);
|
||||
UNLOCK_L;
|
||||
|
||||
if (sock < 0) {
|
||||
LOG_ERROR("failed to create socket");
|
||||
|
||||
Reference in New Issue
Block a user