Merge pull request #357 from KLuka/issue-222

Issue #222: LOGIN service (can't reopen tty)
This commit is contained in:
Luka Krajger 2016-01-04 10:56:18 -05:00
commit 2c93404bd0
3 changed files with 32 additions and 2 deletions

View file

@ -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;

View file

@ -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;

View file

@ -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);