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;
|
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) {
|
static bool create_socket_dir(struct sockaddr_un *sockaddr) {
|
||||||
sockaddr->sun_path[0] = '\0';
|
sockaddr->sun_path[0] = '\0';
|
||||||
uid_t uid = getuid();
|
uid_t uid = getuid();
|
||||||
|
|
@ -348,6 +376,11 @@ static bool create_session(const char *name, char * const argv[]) {
|
||||||
char errormsg[255];
|
char errormsg[255];
|
||||||
struct sigaction sa;
|
struct sigaction sa;
|
||||||
|
|
||||||
|
if (session_exists(name)) {
|
||||||
|
errno = EADDRINUSE;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (pipe(client_pipe) == -1)
|
if (pipe(client_pipe) == -1)
|
||||||
return false;
|
return false;
|
||||||
if ((server.socket = server_create_socket(name)) == -1)
|
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) {
|
static bool attach_session(const char *name, const bool terminate) {
|
||||||
if (server.socket > 0)
|
if (server.socket > 0)
|
||||||
close(server.socket);
|
close(server.socket);
|
||||||
if (!set_socket_name(&sockaddr, name) || (server.socket = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
|
if ((server.socket = session_connect(name)) == -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)
|
|
||||||
return false;
|
return false;
|
||||||
if (server_set_socket_non_blocking(server.socket) == -1)
|
if (server_set_socket_non_blocking(server.socket) == -1)
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -486,21 +516,6 @@ static bool attach_session(const char *name, const bool terminate) {
|
||||||
return 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) {
|
static int session_filter(const struct dirent *d) {
|
||||||
return strstr(d->d_name, server.host) != NULL;
|
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)) {
|
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));
|
strftime(buf, sizeof(buf), "%a%t %F %T", localtime(&sb.st_atime));
|
||||||
char status = ' ';
|
char status = ' ';
|
||||||
if (sb.st_mode & S_IXUSR)
|
char *local = strstr(namelist[n]->d_name, server.host);
|
||||||
status = '*';
|
if (local) {
|
||||||
else if (sb.st_mode & S_IXGRP)
|
char *name = strdup(namelist[n]->d_name);
|
||||||
status = '+';
|
*local = '\0'; /* truncate hostname if we are local */
|
||||||
char *name = strstr(namelist[n]->d_name, server.host);
|
if (session_alive(namelist[n]->d_name))
|
||||||
if (name)
|
status = '*';
|
||||||
*name = '\0';
|
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);
|
printf("%c %s\t%s\n", status, buf, namelist[n]->d_name);
|
||||||
}
|
}
|
||||||
free(namelist[n]);
|
free(namelist[n]);
|
||||||
|
|
|
||||||
8
server.c
8
server.c
|
|
@ -212,8 +212,10 @@ static void server_mainloop(void) {
|
||||||
}
|
}
|
||||||
kill(-server.pid, SIGWINCH);
|
kill(-server.pid, SIGWINCH);
|
||||||
break;
|
break;
|
||||||
case MSG_DETACH:
|
|
||||||
case MSG_EXIT:
|
case MSG_EXIT:
|
||||||
|
exit_packet_delivered = true;
|
||||||
|
/* fall through */
|
||||||
|
case MSG_DETACH:
|
||||||
c->state = STATE_DISCONNECTED;
|
c->state = STATE_DISCONNECTED;
|
||||||
break;
|
break;
|
||||||
default: /* ignore package */
|
default: /* ignore package */
|
||||||
|
|
@ -249,9 +251,7 @@ static void server_mainloop(void) {
|
||||||
.u.i = server.exit_status,
|
.u.i = server.exit_status,
|
||||||
.len = sizeof(pkt.u.i),
|
.len = sizeof(pkt.u.i),
|
||||||
};
|
};
|
||||||
if (server_send_packet(c, &pkt))
|
if (!server_send_packet(c, &pkt))
|
||||||
exit_packet_delivered = true;
|
|
||||||
else
|
|
||||||
FD_SET_MAX(c->socket, &new_writefds, new_fdmax);
|
FD_SET_MAX(c->socket, &new_writefds, new_fdmax);
|
||||||
} else {
|
} else {
|
||||||
FD_SET_MAX(c->socket, &new_writefds, new_fdmax);
|
FD_SET_MAX(c->socket, &new_writefds, new_fdmax);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue