Compare commits

..
3 Commits
47 .. 48
Author SHA1 Message Date
Auke Kok dc376d5e8b Update to v48 2019-01-15 12:47:32 -08:00
Auke Kok c831ecb902 Use select() to time out, and exit.
With socket activation, we can now select() and time out before accept()
and exit, releasing all resource we used back to the system.

The default timeout is set for 10 minutes. If no more connections
arrive, the daemon exits.

Socket activation is done through the clr_debug_daemon.socket unit, which
the clr_debug_fuse service requires, so this should be extra robust when
starting up.

The daemon ignores stat() requests for trash that gnome sends when it
sees the fuse system mounted, and returns the underlying stat() for
the root node instead of a remote value, because there is no value
in fetching this info over curl.
2019-01-09 12:58:42 -08:00
Auke Kok 0978d429b2 Clean up some of the socket activation stuff. 2019-01-08 12:37:56 -08:00
5 changed files with 69 additions and 37 deletions
+2 -1
View File
@@ -1,6 +1,7 @@
[Unit] [Unit]
Description=Clear Linux debuginfo fuse monitor Description=Clear Linux debuginfo fuse monitor
After=clr_debug_daemon.service After=clr_debug_daemon.socket
Requires=clr_debug_daemon.socket
DefaultDependencies=no DefaultDependencies=no
[Service] [Service]
+3 -1
View File
@@ -2,7 +2,7 @@
# Process this file with autoconf to produce a configure script. # Process this file with autoconf to produce a configure script.
AC_PREREQ([2.66]) AC_PREREQ([2.66])
AC_INIT(clr-debug-info, 47, arjan@linux.intel.com) AC_INIT(clr-debug-info, 48, arjan@linux.intel.com)
AM_INIT_AUTOMAKE([foreign -Wall -W subdir-objects]) AM_INIT_AUTOMAKE([foreign -Wall -W subdir-objects])
AM_SILENT_RULES([yes]) AM_SILENT_RULES([yes])
AC_PROG_CC AC_PROG_CC
@@ -15,6 +15,8 @@ PKG_CHECK_MODULES([SYSTEMD], [systemd])
PKG_CHECK_MODULES([LIBSYSTEMD], [libsystemd]) PKG_CHECK_MODULES([LIBSYSTEMD], [libsystemd])
LT_INIT LT_INIT
AC_DEFINE([SOCKET_PATH], ["/run/clr-debug-info"], [path to communication socket])
dir="" dir=""
AC_ARG_WITH([systemdsystemunitdir], AS_HELP_STRING([--with-systemdsystemunitdir=DIR], AC_ARG_WITH([systemdsystemunitdir], AS_HELP_STRING([--with-systemdsystemunitdir=DIR],
[path to systemd system service dir @<:@default=/usr/lib/systemd/system@:>@]), [dir=${withval}], [path to systemd system service dir @<:@default=/usr/lib/systemd/system@:>@]), [dir=${withval}],
+6 -4
View File
@@ -36,6 +36,8 @@
#include <time.h> #include <time.h>
#include <unistd.h> #include <unistd.h>
#include "config.h"
/* 0.75 seconds timeout */ /* 0.75 seconds timeout */
#define TIMEOUT 75000 #define TIMEOUT 75000
#define TIMEOUT2 1500 #define TIMEOUT2 1500
@@ -58,7 +60,7 @@ void try_to_get(const char *path, int pid, time_t timestamp)
int shorttime = 0; int shorttime = 0;
__nc_unused__ size_t wr = -1; __nc_unused__ size_t wr = -1;
// printf("Trying to aquire %s\n", path); // printf("Trying to aquire %s\n", path);
sockfd = socket(AF_UNIX, SOCK_STREAM, 0); sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
if (sockfd < 0) { if (sockfd < 0) {
@@ -66,13 +68,13 @@ void try_to_get(const char *path, int pid, time_t timestamp)
} }
sun.sun_family = AF_UNIX; sun.sun_family = AF_UNIX;
strcpy(sun.sun_path, "/run/clr-debug-info"); strcpy(sun.sun_path, SOCKET_PATH);
ret = connect(sockfd, ret = connect(sockfd,
(struct sockaddr *)&sun, (struct sockaddr *)&sun,
offsetof(struct sockaddr_un, sun_path) + strlen("/run/clr-debug-info") + 1); offsetof(struct sockaddr_un, sun_path) + strlen(SOCKET_PATH) + 1);
if (ret < 0) { if (ret < 0) {
printf("Cannot connect %s\n", strerror(errno)); printf("Cannot connect to %s: %s\n", SOCKET_PATH, strerror(errno));
close(sockfd); close(sockfd);
return; return;
} }
+10
View File
@@ -75,6 +75,16 @@ static int xmp_getattr(const char *path, struct stat *stbuf)
memset(stbuf, 0, sizeof(struct stat)); memset(stbuf, 0, sizeof(struct stat));
res = lstat(newpath, stbuf); res = lstat(newpath, stbuf);
/*
* filter out things that never should get fetched
* this prevents us from asking curl to fetch us useless things
*/
if (strncmp(path, "/.Trash", strlen("/.Trash")) == 0) {
return -ENOENT;
} else if (strcmp(path, "/") == 0) {
return 0;
}
/* /*
* get the file. if the st_mtime is set, this is just an async refresh, otherwise it's * get the file. if the st_mtime is set, this is just an async refresh, otherwise it's
* a synchronous request. * a synchronous request.
+48 -31
View File
@@ -57,6 +57,8 @@
#include <stdatomic.h> #include <stdatomic.h>
#endif #endif
#define TIMEOUT 600 /* 10 minutes */
static pthread_mutex_t dupes_mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t dupes_mutex = PTHREAD_MUTEX_INITIALIZER;
char *urls[2] = { "https://cdn.download.clearlinux.org/debuginfo/", char *urls[2] = { "https://cdn.download.clearlinux.org/debuginfo/",
@@ -431,54 +433,71 @@ int main(__nc_unused__ int argc, __nc_unused__ char **argv)
signal(SIGPIPE, SIG_IGN); signal(SIGPIPE, SIG_IGN);
if (sd_listen_fds(0) == 1) { if (sd_listen_fds(0) == 1) {
/* systemd socket activation */ /* systemd socket activation */
printf("Received socket from systemd socket activation\n"); sockfd = SD_LISTEN_FDS_START + 0;
sockfd = SD_LISTEN_FDS_START + 0; } else if (sd_listen_fds(0) > 1) {
} else if (sd_listen_fds(0) > 1) { printf("Too many file descriptors received.\n");
printf("Too many file descriptors received.\n"); exit(EXIT_FAILURE);
exit(1); } else {
} else { sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
sockfd = socket(AF_UNIX, SOCK_STREAM, 0); if (sockfd < 0) {
if (sockfd < 0) { exit(EXIT_FAILURE);
return EXIT_FAILURE; }
}
sun.sun_family = AF_UNIX; sun.sun_family = AF_UNIX;
strcpy(sun.sun_path, "/run/clr-debug-info"); strcpy(sun.sun_path, SOCKET_PATH);
ret = bind(sockfd, ret = bind(sockfd,
(struct sockaddr *)&sun, (struct sockaddr *)&sun,
offsetof(struct sockaddr_un, sun_path) + strlen("/run/clr-debug-info") + 1); offsetof(struct sockaddr_un, sun_path) + strlen(SOCKET_PATH) + 1);
if (ret < 0) { if (ret < 0) {
printf("Failed to bind:%s \n", strerror(errno)); fprintf(stderr, "Failed to bind:%s \n", strerror(errno));
return EXIT_FAILURE; exit(EXIT_FAILURE);
} }
if (listen(sockfd, 16) < 0) { if (listen(sockfd, 16) < 0) {
printf("Failed to listen:%s \n", strerror(errno)); fprintf(stderr, "Failed to listen:%s \n", strerror(errno));
return EXIT_FAILURE; exit(EXIT_FAILURE);
} }
} }
if (setgid(dbg_group)) { if (setgid(dbg_group)) {
fprintf(stderr, "Unable to drop privileges setgid %s\n", strerror(errno)); fprintf(stderr, "Unable to drop privileges setgid %s\n", strerror(errno));
return EXIT_FAILURE; exit(EXIT_FAILURE);
} }
if (setgroups(1, &dbg_group)) { if (setgroups(1, &dbg_group)) {
fprintf(stderr, "Unable to drop privileges setgroups %s\n", strerror(errno)); fprintf(stderr, "Unable to drop privileges setgroups %s\n", strerror(errno));
return EXIT_FAILURE; exit(EXIT_FAILURE);
} }
if (setuid(dbg_user)) { if (setuid(dbg_user)) {
fprintf(stderr, "Unable to drop privileges setuid %s\n", strerror(errno)); fprintf(stderr, "Unable to drop privileges setuid %s\n", strerror(errno));
return EXIT_FAILURE; exit(EXIT_FAILURE);
} }
while (1) { while (1) {
fd_set rfds;
struct timeval tv;
int ret;
int clientsock; int clientsock;
pthread_t thread; pthread_t thread;
malloc_trim(0); malloc_trim(0);
/* use select() to timeout and exit gracefully */
FD_ZERO(&rfds);
FD_SET(sockfd, &rfds);
tv.tv_sec = TIMEOUT;
tv.tv_usec = 0;
ret = select(sockfd + 1, &rfds, NULL, NULL, &tv);
if (ret == -1) {
perror("select()");
exit(EXIT_FAILURE);
} else if (ret == 0) {
break;
}
clientsock = accept(sockfd, NULL, NULL); clientsock = accept(sockfd, NULL, NULL);
/* Too many connections, wait for the next loop/retry */ /* Too many connections, wait for the next loop/retry */
@@ -503,6 +522,4 @@ int main(__nc_unused__ int argc, __nc_unused__ char **argv)
if (hash) { if (hash) {
nc_hashmap_free(hash); nc_hashmap_free(hash);
} }
close(sockfd);
} }