backport 2/2 from https://gitlab.xiph.org/xiph/vorbis-tools/-/merge_requests/27.patch From cfc497a442f51fb4885e132deaf2e0ba067bd280 Mon Sep 17 00:00:00 2001 From: "Timothy B. Terriberry" Date: Tue, 24 Jun 2025 09:38:56 -0700 Subject: [PATCH 2/2] ogg123: Handle EOF/error in remote interface Previously, if there was an error or EOF reading commands for the remote interface, the reader would loop infinitely trying to read another command that will never come. Instead, treat error or EOF as a Quit command. We manually send an error message / log, instead of using the existing error path, because we still want the main thread to process the Quit. --- a/ogg123/remote.c +++ b/ogg123/remote.c @@ -139,6 +139,7 @@ static void * remotethread(void * arg) { buf[MAXBUF]=0; while(!done) { + char *ret; /* Read a line */ buf[0] = 0; send_log("Waiting for input: ..."); @@ -149,77 +150,86 @@ static void * remotethread(void * arg) { select (1, &fd, NULL, NULL, NULL); #endif - fgets(buf, MAXBUF, stdin); - buf[strcspn(buf, "\n")] = 0; + ret = fgets(buf, MAXBUF, stdin); /* Lock on */ pthread_mutex_lock (&main_lock); - send_log("Input: %s", buf); - error = 0; - - if (!strncasecmp(buf,"l",1)) { - /* prepare to load */ - if ((b=strchr(buf,' ')) != NULL) { - /* Prepare to load a new song */ - strcpy((char*)arg, b+1); + if (ret != NULL) { + buf[strcspn(buf, "\n")] = 0; + send_log("Input: %s", buf); + error = 0; + + if (!strncasecmp(buf,"l",1)) { + /* prepare to load */ + if ((b=strchr(buf,' ')) != NULL) { + /* Prepare to load a new song */ + strcpy((char*)arg, b+1); + setstatus(NEXT); + } + else { + /* Invalid load command */ + error = 1; + } + } + else + if (!strncasecmp(buf,"p",1)) { + /* Prepare to (un)pause */ + invertpause(); + } + else + if (!strncasecmp(buf,"j",1)) { + /* Prepare to seek */ + if ((b=strchr(buf,' ')) != NULL) { + set_seek_opt(&options, b+1); + } + ignore = 1; + } + else + if (!strncasecmp(buf,"s",1)) { + /* Prepare to stop */ + setstatus(STOP); + } + else + if (!strncasecmp(buf,"r",1)) { + /* Prepare to reload */ setstatus(NEXT); - } + } + else + if (!strncasecmp(buf,"h",1)) { + /* Send help */ + send_msg("H +----------------------------------------------------+"); + send_msg("H | Ogg123 remote interface |"); + send_msg("H |----------------------------------------------------|"); + send_msg("H | Load - load a file and starts playing |"); + send_msg("H | Pause - pause or unpause playing |"); + send_msg("H | Jump [+|-] - jump seconds forth or back |"); + send_msg("H | Stop - stop playing |"); + send_msg("H | Reload - reload last song |"); + send_msg("H | Quit - quit ogg123 |"); + send_msg("H |----------------------------------------------------|"); + send_msg("H | refer to README.remote for documentation |"); + send_msg("H +----------------------------------------------------+"); + ignore = 1; + } + else + if (!strncasecmp(buf,"q",1)) { + /* Prepare to quit */ + setstatus(QUIT); + done = 1; + } else { - /* Invalid load command */ + /* Unknown input received */ error = 1; } } - else - if (!strncasecmp(buf,"p",1)) { - /* Prepare to (un)pause */ - invertpause(); - } - else - if (!strncasecmp(buf,"j",1)) { - /* Prepare to seek */ - if ((b=strchr(buf,' ')) != NULL) { - set_seek_opt(&options, b+1); - } - ignore = 1; - } - else - if (!strncasecmp(buf,"s",1)) { - /* Prepare to stop */ - setstatus(STOP); - } - else - if (!strncasecmp(buf,"r",1)) { - /* Prepare to reload */ - setstatus(NEXT); - } - else - if (!strncasecmp(buf,"h",1)) { - /* Send help */ - send_msg("H +----------------------------------------------------+"); - send_msg("H | Ogg123 remote interface |"); - send_msg("H |----------------------------------------------------|"); - send_msg("H | Load - load a file and starts playing |"); - send_msg("H | Pause - pause or unpause playing |"); - send_msg("H | Jump [+|-] - jump seconds forth or back |"); - send_msg("H | Stop - stop playing |"); - send_msg("H | Reload - reload last song |"); - send_msg("H | Quit - quit ogg123 |"); - send_msg("H |----------------------------------------------------|"); - send_msg("H | refer to README.remote for documentation |"); - send_msg("H +----------------------------------------------------+"); - ignore = 1; - } - else - if (!strncasecmp(buf,"q",1)) { - /* Prepare to quit */ + else { + send_err("E EOF or error reading commands"); + send_log("EOF or error reading commands"); + /* Treat EOF or error as a quit command. */ setstatus(QUIT); done = 1; } - else { - /* Unknown input received */ - error = 1; - } if (ignore) { /* Unlock */