forked from github/abduco
Improve detection and handling of stale sessions
With this it should be possible to create sessions for which a dead left over socket still exists. Also the session list as printed by abduco without any arguments will delete those stale sockets.
This commit is contained in:
parent
91feaaa9f9
commit
277f4d154d
81
abduco.c
81
abduco.c
|
|
@ -236,6 +236,34 @@ static bool xsnprintf(char *buf, size_t size, const char *fmt, ...) {
|
|||
return true;
|
||||
}
|
||||
|
||||
static int session_connect(const char *name) {
|
||||
int fd;
|
||||
if (!set_socket_name(&sockaddr, name) || (fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
|
||||
return -1;
|
||||
socklen_t socklen = offsetof(struct sockaddr_un, sun_path) + strlen(sockaddr.sun_path) + 1;
|
||||
if (connect(fd, (struct sockaddr*)&sockaddr, socklen) == -1) {
|
||||
if (errno == ECONNREFUSED)
|
||||
unlink(sockaddr.sun_path);
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
|
||||
static bool session_exists(const char *name) {
|
||||
int fd = session_connect(name);
|
||||
if (fd != -1)
|
||||
close(fd);
|
||||
return fd != -1;
|
||||
}
|
||||
|
||||
static bool session_alive(const char *name) {
|
||||
struct stat sb;
|
||||
return session_exists(name) &&
|
||||
stat(sockaddr.sun_path, &sb) == 0 &&
|
||||
S_ISSOCK(sb.st_mode) && (sb.st_mode & S_IXGRP) == 0;
|
||||
}
|
||||
|
||||
static bool create_socket_dir(struct sockaddr_un *sockaddr) {
|
||||
sockaddr->sun_path[0] = '\0';
|
||||
uid_t uid = getuid();
|
||||
|
|
@ -348,6 +376,11 @@ static bool create_session(const char *name, char * const argv[]) {
|
|||
char errormsg[255];
|
||||
struct sigaction sa;
|
||||
|
||||
if (session_exists(name)) {
|
||||
errno = EADDRINUSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pipe(client_pipe) == -1)
|
||||
return false;
|
||||
if ((server.socket = server_create_socket(name)) == -1)
|
||||
|
|
@ -454,10 +487,7 @@ static bool create_session(const char *name, char * const argv[]) {
|
|||
static bool attach_session(const char *name, const bool terminate) {
|
||||
if (server.socket > 0)
|
||||
close(server.socket);
|
||||
if (!set_socket_name(&sockaddr, name) || (server.socket = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
|
||||
return false;
|
||||
socklen_t socklen = offsetof(struct sockaddr_un, sun_path) + strlen(sockaddr.sun_path) + 1;
|
||||
if (connect(server.socket, (struct sockaddr*)&sockaddr, socklen) == -1)
|
||||
if ((server.socket = session_connect(name)) == -1)
|
||||
return false;
|
||||
if (server_set_socket_non_blocking(server.socket) == -1)
|
||||
return false;
|
||||
|
|
@ -486,21 +516,6 @@ static bool attach_session(const char *name, const bool terminate) {
|
|||
return terminate;
|
||||
}
|
||||
|
||||
static bool session_exists(const char *name) {
|
||||
struct stat sb;
|
||||
if (!set_socket_name(&sockaddr, name))
|
||||
return false;
|
||||
return stat(sockaddr.sun_path, &sb) == 0 && S_ISSOCK(sb.st_mode);
|
||||
}
|
||||
|
||||
static bool session_alive(const char *name) {
|
||||
struct stat sb;
|
||||
if (!set_socket_name(&sockaddr, name))
|
||||
return false;
|
||||
return stat(sockaddr.sun_path, &sb) == 0 && S_ISSOCK(sb.st_mode) &&
|
||||
(sb.st_mode & S_IXGRP) == 0;
|
||||
}
|
||||
|
||||
static int session_filter(const struct dirent *d) {
|
||||
return strstr(d->d_name, server.host) != NULL;
|
||||
}
|
||||
|
|
@ -528,13 +543,27 @@ static int list_session(void) {
|
|||
if (stat(namelist[n]->d_name, &sb) == 0 && S_ISSOCK(sb.st_mode)) {
|
||||
strftime(buf, sizeof(buf), "%a%t %F %T", localtime(&sb.st_atime));
|
||||
char status = ' ';
|
||||
if (sb.st_mode & S_IXUSR)
|
||||
status = '*';
|
||||
else if (sb.st_mode & S_IXGRP)
|
||||
status = '+';
|
||||
char *name = strstr(namelist[n]->d_name, server.host);
|
||||
if (name)
|
||||
*name = '\0';
|
||||
char *local = strstr(namelist[n]->d_name, server.host);
|
||||
if (local) {
|
||||
char *name = strdup(namelist[n]->d_name);
|
||||
*local = '\0'; /* truncate hostname if we are local */
|
||||
if (session_alive(namelist[n]->d_name))
|
||||
status = '*';
|
||||
else if (session_exists(namelist[n]->d_name))
|
||||
status = '+';
|
||||
/* check if the socket is still valid, session_{alive,exists}
|
||||
* might have deleted it */
|
||||
if (name && stat(name, &sb) == -1) {
|
||||
free(name);
|
||||
continue;
|
||||
}
|
||||
free(name);
|
||||
} else {
|
||||
if (sb.st_mode & S_IXUSR)
|
||||
status = '*';
|
||||
else if (sb.st_mode & S_IXGRP)
|
||||
status = '+';
|
||||
}
|
||||
printf("%c %s\t%s\n", status, buf, namelist[n]->d_name);
|
||||
}
|
||||
free(namelist[n]);
|
||||
|
|
|
|||
8
server.c
8
server.c
|
|
@ -212,8 +212,10 @@ static void server_mainloop(void) {
|
|||
}
|
||||
kill(-server.pid, SIGWINCH);
|
||||
break;
|
||||
case MSG_DETACH:
|
||||
case MSG_EXIT:
|
||||
exit_packet_delivered = true;
|
||||
/* fall through */
|
||||
case MSG_DETACH:
|
||||
c->state = STATE_DISCONNECTED;
|
||||
break;
|
||||
default: /* ignore package */
|
||||
|
|
@ -249,9 +251,7 @@ static void server_mainloop(void) {
|
|||
.u.i = server.exit_status,
|
||||
.len = sizeof(pkt.u.i),
|
||||
};
|
||||
if (server_send_packet(c, &pkt))
|
||||
exit_packet_delivered = true;
|
||||
else
|
||||
if (!server_send_packet(c, &pkt))
|
||||
FD_SET_MAX(c->socket, &new_writefds, new_fdmax);
|
||||
} else {
|
||||
FD_SET_MAX(c->socket, &new_writefds, new_fdmax);
|
||||
|
|
|
|||
Loading…
Reference in New Issue