public inbox for lvm2-cvs@sourceware.org
help / color / mirror / Atom feed
* LVM2/daemons/common daemon-server.c
@ 2012-01-25 21:30 zkabelac
  0 siblings, 0 replies; 5+ messages in thread
From: zkabelac @ 2012-01-25 21:30 UTC (permalink / raw)
  To: lvm-devel, lvm2-cvs

CVSROOT:	/cvs/lvm2
Module name:	LVM2
Changes by:	zkabelac@sourceware.org	2012-01-25 21:30:28

Modified files:
	daemons/common : daemon-server.c 

Log message:
	Check and print perror for syscalls

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/daemons/common/daemon-server.c.diff?cvsroot=lvm2&r1=1.15&r2=1.16

--- LVM2/daemons/common/daemon-server.c	2012/01/15 10:33:41	1.15
+++ LVM2/daemons/common/daemon-server.c	2012/01/25 21:30:27	1.16
@@ -129,8 +129,10 @@
 
 error:
 	if (fd >= 0) {
-		close(fd);
-		unlink(s.socket_path);
+		if (close(fd))
+			perror("close failed");
+		if (unlink(s.socket_path))
+			perror("unlink failed");
 		fd = -1;
 	}
 	goto out;
@@ -364,7 +366,8 @@
 	}
 
 	if (s.socket_fd >= 0)
-		unlink(s.socket_path);
+		if (unlink(s.socket_path))
+			perror("unlink error");
 
 	if (s.daemon_fini)
 		s.daemon_fini(&s);


^ permalink raw reply	[flat|nested] 5+ messages in thread

* LVM2/daemons/common daemon-server.c
@ 2012-02-28 14:25 zkabelac
  0 siblings, 0 replies; 5+ messages in thread
From: zkabelac @ 2012-02-28 14:25 UTC (permalink / raw)
  To: lvm-devel, lvm2-cvs

CVSROOT:	/cvs/lvm2
Module name:	LVM2
Changes by:	zkabelac@sourceware.org	2012-02-28 14:25:37

Modified files:
	daemons/common : daemon-server.c 

Log message:
	Check for failing dm_asprintf

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/daemons/common/daemon-server.c.diff?cvsroot=lvm2&r1=1.18&r2=1.19

--- LVM2/daemons/common/daemon-server.c	2012/02/28 13:05:21	1.18
+++ LVM2/daemons/common/daemon-server.c	2012/02/28 14:25:37	1.19
@@ -339,18 +339,23 @@
 
 static int buffer_rewrite(char **buf, const char *format, const char *string) {
 	char *old = *buf;
-	dm_asprintf(buf, format, *buf, string);
+	int r = dm_asprintf(buf, format, *buf, string);
+
 	dm_free(old);
-	return 0;
+
+	return (r < 0) ? 0 : 1;
 }
 
 static int buffer_line(const char *line, void *baton) {
 	response *r = baton;
-	if (r->buffer)
-		buffer_rewrite(&r->buffer, "%s\n%s", line);
-	else
-		dm_asprintf(&r->buffer, "%s\n", line);
-	return 0;
+
+	if (r->buffer) {
+		if (!buffer_rewrite(&r->buffer, "%s\n%s", line))
+			return 0;
+	} else if (dm_asprintf(&r->buffer, "%s\n", line) < 0)
+		return 0;
+
+	return 1;
 }
 
 static response builtin_handler(daemon_state s, client_handle h, request r)
@@ -387,7 +392,8 @@
 
 		if (!res.buffer) {
 			dm_config_write_node(res.cft->root, buffer_line, &res);
-			buffer_rewrite(&res.buffer, "%s\n\n", NULL);
+			if (!buffer_rewrite(&res.buffer, "%s\n\n", NULL))
+				goto fail;
 			dm_config_destroy(res.cft);
 		}
 


^ permalink raw reply	[flat|nested] 5+ messages in thread

* LVM2/daemons/common daemon-server.c
@ 2012-02-28 13:05 prajnoha
  0 siblings, 0 replies; 5+ messages in thread
From: prajnoha @ 2012-02-28 13:05 UTC (permalink / raw)
  To: lvm-devel, lvm2-cvs

CVSROOT:	/cvs/lvm2
Module name:	LVM2
Changes by:	prajnoha@sourceware.org	2012-02-28 13:05:21

Modified files:
	daemons/common : daemon-server.c 

Log message:
	Add support for systemd socket handover for common daemon-server code and also add support for new OOM killer adjustment interface.
	
	This code is already a part of dmeventd, but it's modified slightly to check
	sockets instead of FIFOs.

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/daemons/common/daemon-server.c.diff?cvsroot=lvm2&r1=1.17&r2=1.18

--- LVM2/daemons/common/daemon-server.c	2012/02/23 23:52:11	1.17
+++ LVM2/daemons/common/daemon-server.c	2012/02/28 13:05:21	1.18
@@ -43,6 +43,7 @@
 #endif
 
 static volatile sig_atomic_t _shutdown_requested = 0;
+static int _systemd_activation = 0;
 
 static void _exit_handler(int sig __attribute__((unused)))
 {
@@ -50,41 +51,148 @@
 }
 
 #ifdef linux
-#  define OOM_ADJ_FILE "/proc/self/oom_adj"
-#  include <stdio.h>
+
+#include <stddef.h>
+
+/*
+ * Kernel version 2.6.36 and higher has
+ * new OOM killer adjustment interface.
+ */
+#  define OOM_ADJ_FILE_OLD "/proc/self/oom_adj"
+#  define OOM_ADJ_FILE "/proc/self/oom_score_adj"
 
 /* From linux/oom.h */
+/* Old interface */
 #  define OOM_DISABLE (-17)
 #  define OOM_ADJUST_MIN (-16)
+/* New interface */
+#  define OOM_SCORE_ADJ_MIN (-1000)
+
+/* Systemd on-demand activation support */
+#  define SD_LISTEN_PID_ENV_VAR_NAME "LISTEN_PID"
+#  define SD_LISTEN_FDS_ENV_VAR_NAME "LISTEN_FDS"
+#  define SD_LISTEN_FDS_START 3
+#  define SD_FD_SOCKET_SERVER SD_LISTEN_FDS_START
+
+#  include <stdio.h>
+
+static int _set_oom_adj(const char *oom_adj_path, int val)
+{
+	FILE *fp;
+
+	if (!(fp = fopen(oom_adj_path, "w"))) {
+		perror("oom_adj: fopen failed");
+		return 0;
+	}
+
+	fprintf(fp, "%i", val);
+
+	if (dm_fclose(fp))
+		perror("oom_adj: fclose failed");
+
+	return 1;
+}
 
 /*
  * Protection against OOM killer if kernel supports it
  */
-static int _set_oom_adj(int val)
+static int _protect_against_oom_killer(void)
 {
-	FILE *fp;
-
 	struct stat st;
 
 	if (stat(OOM_ADJ_FILE, &st) == -1) {
-		if (errno == ENOENT)
-			perror(OOM_ADJ_FILE " not found");
-		else
+		if (errno != ENOENT)
 			perror(OOM_ADJ_FILE ": stat failed");
-		return 1;
+
+		/* Try old oom_adj interface as a fallback */
+		if (stat(OOM_ADJ_FILE_OLD, &st) == -1) {
+			if (errno == ENOENT)
+				perror(OOM_ADJ_FILE_OLD " not found");
+			else
+				perror(OOM_ADJ_FILE_OLD ": stat failed");
+			return 1;
+		}
+
+		return _set_oom_adj(OOM_ADJ_FILE_OLD, OOM_DISABLE) ||
+		       _set_oom_adj(OOM_ADJ_FILE_OLD, OOM_ADJUST_MIN);
 	}
 
-	if (!(fp = fopen(OOM_ADJ_FILE, "w"))) {
-		perror(OOM_ADJ_FILE ": fopen failed");
+	return _set_oom_adj(OOM_ADJ_FILE, OOM_SCORE_ADJ_MIN);
+}
+
+union sockaddr_union {
+	struct sockaddr sa;
+	struct sockaddr_un un;
+};
+
+static int _handle_preloaded_socket(int fd, const char *path)
+{
+	struct stat st_fd;
+	union sockaddr_union sockaddr;
+	int type = 0;
+	socklen_t len = sizeof(type);
+	size_t path_len = strlen(path);
+
+	if (fd < 0)
 		return 0;
-	}
 
-	fprintf(fp, "%i", val);
-	if (fclose(fp))
-		perror(OOM_ADJ_FILE ": fclose failed");
+	if (fstat(fd, &st_fd) < 0 || !S_ISSOCK(st_fd.st_mode))
+		return 0;
+
+	if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &type, &len) < 0 ||
+	    len != sizeof(type) || type != SOCK_STREAM)
+		return 0;
+
+	memset(&sockaddr, 0, sizeof(sockaddr));
+	len = sizeof(sockaddr);
+	if (getsockname(fd, &sockaddr.sa, &len) < 0 ||
+	    len < sizeof(sa_family_t) ||
+	    sockaddr.sa.sa_family != PF_UNIX)
+		return 0;
+
+	if (!(len >= offsetof(struct sockaddr_un, sun_path) + path_len + 1 &&
+	      memcmp(path, sockaddr.un.sun_path, path_len) == 0))
+		return 0;
 
 	return 1;
 }
+
+static int _systemd_handover(struct daemon_state *ds)
+{
+	const char *e;
+	char *p;
+	unsigned long env_pid, env_listen_fds;
+	int r = 0;
+
+	/* LISTEN_PID must be equal to our PID! */
+	if (!(e = getenv(SD_LISTEN_PID_ENV_VAR_NAME)))
+		goto out;
+
+	errno = 0;
+	env_pid = strtoul(e, &p, 10);
+	if (errno || !p || *p || env_pid <= 0 ||
+	    getpid() != (pid_t) env_pid)
+		;
+
+	/* LISTEN_FDS must be 1 and the fd must be a socket! */
+	if (!(e = getenv(SD_LISTEN_FDS_ENV_VAR_NAME)))
+		goto out;
+
+	errno = 0;
+	env_listen_fds = strtoul(e, &p, 10);
+	if (errno || !p || *p || env_listen_fds != 1)
+		goto out;
+
+	/* Check and handle the socket passed in */
+	if ((r = _handle_preloaded_socket(SD_FD_SOCKET_SERVER, ds->socket_path)))
+		ds->socket_fd = SD_FD_SOCKET_SERVER;
+
+out:
+	unsetenv(SD_LISTEN_PID_ENV_VAR_NAME);
+	unsetenv(SD_LISTEN_FDS_ENV_VAR_NAME);
+	return r;
+}
+
 #endif
 
 static int _open_socket(daemon_state s)
@@ -192,8 +300,14 @@
 	else
 		fd = rlim.rlim_cur;
 
-	for (--fd; fd >= 0; fd--)
+	for (--fd; fd >= 0; fd--) {
+#ifdef linux
+		/* Do not close fds preloaded by systemd! */
+		if (_systemd_activation && fd == SD_FD_SOCKET_SERVER)
+			continue;
+#endif
 		close(fd);
+	}
 
 	if ((open("/dev/null", O_RDONLY) < 0) ||
 	    (open("/dev/null", O_WRONLY) < 0) ||
@@ -328,6 +442,10 @@
 	if (setenv("LANG", "C", 1))
 		perror("Cannot set LANG to C");
 
+#ifdef linux
+	_systemd_activation = _systemd_handover(&s);
+#endif
+
 	if (!s.foreground)
 		_daemonise();
 
@@ -354,11 +472,12 @@
 	signal(SIGPIPE, SIG_IGN);
 
 #ifdef linux
-	if (s.avoid_oom && !_set_oom_adj(OOM_DISABLE) && !_set_oom_adj(OOM_ADJUST_MIN))
-		syslog(LOG_ERR, "Failed to set oom_adj to protect against OOM killer");
+	/* Systemd has adjusted oom killer for us already */
+	if (s.avoid_oom && !_systemd_activation && !_protect_against_oom_killer())
+		syslog(LOG_ERR, "Failed to protect against OOM killer");
 #endif
 
-	if (s.socket_path) {
+	if (!_systemd_activation && s.socket_path) {
 		s.socket_fd = _open_socket(s);
 		if (s.socket_fd < 0)
 			failed = 1;


^ permalink raw reply	[flat|nested] 5+ messages in thread

* LVM2/daemons/common daemon-server.c
@ 2012-01-15 10:33 mornfall
  0 siblings, 0 replies; 5+ messages in thread
From: mornfall @ 2012-01-15 10:33 UTC (permalink / raw)
  To: lvm-devel, lvm2-cvs

CVSROOT:	/cvs/lvm2
Module name:	LVM2
Changes by:	mornfall@sourceware.org	2012-01-15 10:33:41

Modified files:
	daemons/common : daemon-server.c 

Log message:
	Fix a couple of resource leaks in daemon-common server code -- filehandles and
	unjoined threads were leaked for each connection.

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/daemons/common/daemon-server.c.diff?cvsroot=lvm2&r1=1.14&r2=1.15

--- LVM2/daemons/common/daemon-server.c	2011/09/17 14:49:18	1.14
+++ LVM2/daemons/common/daemon-server.c	2012/01/15 10:33:41	1.15
@@ -251,9 +251,6 @@
 		if (!req.cft)
 			fprintf(stderr, "error parsing request:\n %s\n", req.buffer);
 		res = b->s.handler(b->s, b->client, req);
-		if (req.cft)
-			dm_config_destroy(req.cft);
-		dm_free(req.buffer);
 
 		if (!res.buffer) {
 			dm_config_write_node(res.cft->root, buffer_line, &res);
@@ -261,12 +258,17 @@
 			dm_config_destroy(res.cft);
 		}
 
+		if (req.cft)
+			dm_config_destroy(req.cft);
+		dm_free(req.buffer);
+
 		write_buffer(b->client.socket_fd, res.buffer, strlen(res.buffer));
 
 		free(res.buffer);
 	}
 fail:
 	/* TODO what should we really do here? */
+	close(b->client.socket_fd);
 	free(baton);
 	return NULL;
 }
@@ -291,6 +293,8 @@
 	if (pthread_create(&baton->client.thread_id, NULL, client_thread, baton))
 		return 0;
 
+	pthread_detach(baton->client.thread_id);
+
 	return 1;
 }
 


^ permalink raw reply	[flat|nested] 5+ messages in thread

* LVM2/daemons/common daemon-server.c
@ 2011-07-20 18:23 mornfall
  0 siblings, 0 replies; 5+ messages in thread
From: mornfall @ 2011-07-20 18:23 UTC (permalink / raw)
  To: lvm-devel, lvm2-cvs

CVSROOT:	/cvs/lvm2
Module name:	LVM2
Changes by:	mornfall@sourceware.org	2011-07-20 18:23:34

Modified files:
	daemons/common : daemon-server.c 

Log message:
	Fix two small (but eventually unbounded) leaks in daemon-server.c.

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/daemons/common/daemon-server.c.diff?cvsroot=lvm2&r1=1.8&r2=1.9

--- LVM2/daemons/common/daemon-server.c	2011/07/18 14:46:54	1.8
+++ LVM2/daemons/common/daemon-server.c	2011/07/20 18:23:33	1.9
@@ -253,6 +253,7 @@
 		if (!res.buffer) {
 			write_config_node(res.cft->root, buffer_line, &res);
 			buffer_rewrite(&res.buffer, "%s\n\n", NULL);
+			destroy_config_tree(res.cft);
 		}
 
 		write_buffer(b->client.socket_fd, res.buffer, strlen(res.buffer));
@@ -261,6 +262,7 @@
 	}
 fail:
 	/* TODO what should we really do here? */
+	free(baton);
 	return NULL;
 }
 


^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2012-02-28 14:25 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-01-25 21:30 LVM2/daemons/common daemon-server.c zkabelac
  -- strict thread matches above, loose matches on Subject: below --
2012-02-28 14:25 zkabelac
2012-02-28 13:05 prajnoha
2012-01-15 10:33 mornfall
2011-07-20 18:23 mornfall

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).