Bradley Bennett created GUACAMOLE-2238:
------------------------------------------
Summary: Multiple guacamole-server code paths do not correctly
retry on EINTR
Key: GUACAMOLE-2238
URL: https://issues.apache.org/jira/browse/GUACAMOLE-2238
Project: Guacamole
Issue Type: Bug
Components: guacd
Affects Versions: 1.6.0, 1.6.1
Reporter: Bradley Bennett
Several locations in the *guacamole-server* codebase call blocking system calls
(e.g., poll(), select(), read(), etc.) and treat any -1 return value as a fatal
error without checking for {*}errno == EINTR{*}.
Because *EINTR* is triggered asynchronously by signals, this can lead to
intermittent and hard-to-debug failures. In particular, *SIGCHLD* is delivered
whenever a child process exits or changes state (e.g., when forked subprocesses
terminate), which can interrupt blocking syscalls, causing unexpected failures
if *EINTR* is not retried.
One example that has recently been identified asthe core cause of an issue{*}:
src/libguac/wait-fd.c{*}:
{code:java}
int guac_wait_for_fd(int fd, int usec_timeout) {
...
return select(fd + 1, &fds, NULL, NULL, &timeout);{code}
The fix is to retry if the select() fails with EINTR:
{code:java}
int guac_wait_for_fd(int fd, int usec_timeout) {
...
do {
...
/* Retry if interrupted by a signal (EINTR). */
retval = select(fd + 1, &fds, NULL, NULL, &timeout);
} while (retval < 0 && errno == EINTR); return retval;
{code}
The fix (if properly implemented) is {*}very low risk{*}, as it only retries
the syscall when it was interrupted by a signal before completing. In this case
the operation has not actually failed and no state has changed; retrying simply
resumes the original wait as intended.
There are numerous instances where EINTR is not handled properly for the
read(), write(), poll(), select(), waitpid(), and nanosleep() system calls,
--
This message was sent by Atlassian Jira
(v8.20.10#820010)