Issue #222: LOGIN service (can't reopen tty)
* Workaround for random "Session closed" issues related to /bin/login closing and reopening our pty during initialization. This happens only on some systems like Fedora for example. Now we allow that our pty is closed by ignoring POLLHUP on first read. Delay is also needed so that login process has some time to reopen pty. * Note that the issue may occur anyway but with this workaround we reduce the chances.
This commit is contained in:
parent
d8ef7dad3c
commit
4911d0d39c
3 changed files with 32 additions and 2 deletions
|
@ -116,9 +116,11 @@ void initSession(struct Session *session, const char *sessionKey,
|
||||||
session->http = NULL;
|
session->http = NULL;
|
||||||
session->done = 0;
|
session->done = 0;
|
||||||
session->pty = -1;
|
session->pty = -1;
|
||||||
|
session->ptyFirstRead = 1;
|
||||||
session->width = 0;
|
session->width = 0;
|
||||||
session->height = 0;
|
session->height = 0;
|
||||||
session->buffered = NULL;
|
session->buffered = NULL;
|
||||||
|
session->useLogin = 0;
|
||||||
session->len = 0;
|
session->len = 0;
|
||||||
session->pid = 0;
|
session->pid = 0;
|
||||||
session->cleanup = 0;
|
session->cleanup = 0;
|
||||||
|
|
|
@ -58,9 +58,11 @@ struct Session {
|
||||||
HttpConnection *http;
|
HttpConnection *http;
|
||||||
int done;
|
int done;
|
||||||
int pty;
|
int pty;
|
||||||
|
int ptyFirstRead;
|
||||||
int width;
|
int width;
|
||||||
int height;
|
int height;
|
||||||
char *buffered;
|
char *buffered;
|
||||||
|
int useLogin;
|
||||||
int len;
|
int len;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
int cleanup;
|
int cleanup;
|
||||||
|
|
|
@ -63,7 +63,7 @@
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/un.h>
|
#include <sys/un.h>
|
||||||
|
#include <time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#ifdef HAVE_SYS_PRCTL_H
|
#ifdef HAVE_SYS_PRCTL_H
|
||||||
|
@ -291,6 +291,13 @@ static void sessionDone(void *arg) {
|
||||||
completePendingRequest(session, "", 0, INT_MAX);
|
completePendingRequest(session, "", 0, INT_MAX);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void delaySession(void) {
|
||||||
|
struct timespec ts;
|
||||||
|
ts.tv_sec = 0;
|
||||||
|
ts.tv_nsec = 200 * 1000; // Delay for 0.2 ms
|
||||||
|
nanosleep(&ts, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
static int handleSession(struct ServerConnection *connection, void *arg,
|
static int handleSession(struct ServerConnection *connection, void *arg,
|
||||||
short *events, short revents) {
|
short *events, short revents) {
|
||||||
struct Session *session = (struct Session *)arg;
|
struct Session *session = (struct Session *)arg;
|
||||||
|
@ -310,7 +317,7 @@ static int handleSession(struct ServerConnection *connection, void *arg,
|
||||||
int timedOut = serverGetTimeout(connection) < 0;
|
int timedOut = serverGetTimeout(connection) < 0;
|
||||||
if (bytes || timedOut) {
|
if (bytes || timedOut) {
|
||||||
if (!session->http && timedOut) {
|
if (!session->http && timedOut) {
|
||||||
debug("[server] Timeout. Closing session!");
|
debug("[server] Timeout. Closing session %s!", session->sessionKey);
|
||||||
session->cleanup = 1;
|
session->cleanup = 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -324,8 +331,26 @@ static int handleSession(struct ServerConnection *connection, void *arg,
|
||||||
*events = 0;
|
*events = 0;
|
||||||
}
|
}
|
||||||
serverSetTimeout(connection, AJAX_TIMEOUT);
|
serverSetTimeout(connection, AJAX_TIMEOUT);
|
||||||
|
session->ptyFirstRead = 0;
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
|
if (revents & POLLHUP) {
|
||||||
|
if (session->useLogin && session->ptyFirstRead) {
|
||||||
|
// Workaround for random "Session closed" issues related to /bin/login
|
||||||
|
// closing and reopening our pty during initialization. This happens only
|
||||||
|
// on some systems like Fedora for example.
|
||||||
|
// Here we allow that our pty is closed by ignoring POLLHUP on first read.
|
||||||
|
// Delay is also needed so that login process has some time to reopen pty.
|
||||||
|
// Note that the issue may occur anyway but with workaround we reduce the
|
||||||
|
// chances.
|
||||||
|
debug("[server] POLLHUP received on login PTY first read!");
|
||||||
|
session->ptyFirstRead = 0;
|
||||||
|
delaySession();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
debug("[server] POLLHUP received on PTY! Closing session %s!",
|
||||||
|
session->sessionKey);
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -402,6 +427,7 @@ static int dataHandler(HttpConnection *http, struct Service *service,
|
||||||
goto bad_new_session;
|
goto bad_new_session;
|
||||||
}
|
}
|
||||||
session->http = http;
|
session->http = http;
|
||||||
|
session->useLogin = service->useLogin;
|
||||||
if (launchChild(service->id, session,
|
if (launchChild(service->id, session,
|
||||||
rootURL && *rootURL ? rootURL : urlGetURL(url)) < 0) {
|
rootURL && *rootURL ? rootURL : urlGetURL(url)) < 0) {
|
||||||
abandonSession(session);
|
abandonSession(session);
|
||||||
|
|
Loading…
Reference in a new issue