commit 7a356c7: [Minor] Try better to set proctitle on darwin

Vsevolod Stakhov vsevolod at highsecure.ru
Sun Jul 14 08:56:04 UTC 2019


Author: Vsevolod Stakhov
Date: 2019-07-14 09:54:20 +0100
URL: https://github.com/rspamd/rspamd/commit/7a356c782ee05cf9b942e92e381f453d205a9cc1 (HEAD -> master)

[Minor] Try better to set proctitle on darwin

---
 src/libutil/util.c | 340 ++++++++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 274 insertions(+), 66 deletions(-)

diff --git a/src/libutil/util.c b/src/libutil/util.c
index 1f83194ad..86358e46e 100644
--- a/src/libutil/util.c
+++ b/src/libutil/util.c
@@ -785,102 +785,221 @@ rspamd_pass_signal (GHashTable * workers, gint signo)
 
 #ifndef HAVE_SETPROCTITLE
 
-#if !defined(DARWIN) && !defined(SOLARIS) && !defined(__APPLE__)
+#ifdef LINUX
 static gchar *title_buffer = 0;
 static size_t title_buffer_size = 0;
 static gchar *title_progname, *title_progname_full;
 #endif
 
-gint
-setproctitle (const gchar *fmt, ...)
+#ifdef LINUX
+static void
+rspamd_title_dtor (gpointer d)
 {
-#if defined(DARWIN) || defined(SOLARIS) || defined(__APPLE__)
-	GString *dest;
-	va_list ap;
+	gchar **env = (gchar **)d;
+	guint i;
 
-	dest = g_string_new ("");
-	va_start (ap, fmt);
-	rspamd_vprintf_gstring (dest, fmt, ap);
-	va_end (ap);
+	for (i = 0; env[i] != NULL; i++) {
+		g_free (env[i]);
+	}
 
-	g_set_prgname (dest->str);
-	g_string_free (dest, TRUE);
+	g_free (env);
+}
+#endif
 
-	return 0;
-#else
-	if (!title_buffer || !title_buffer_size) {
-		errno = ENOMEM;
-		return -1;
+#ifdef __APPLE__
+
+/* Code is based on darwin-proctitle.c used almost everywhere */
+
+/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include <dlfcn.h>
+#include <TargetConditionals.h>
+#include <CoreFoundation/CoreFoundation.h>
+#include <ApplicationServices/ApplicationServices.h>
+
+/* Darwin is just brain damaged */
+static int (*dynamic_pthread_setname_np)(const char* name);
+static CFStringRef (*pCFStringCreateWithCString)(CFAllocatorRef,
+												 const char*,
+												 CFStringEncoding);
+static CFBundleRef (*pCFBundleGetBundleWithIdentifier)(CFStringRef);
+static void *(*pCFBundleGetDataPointerForName)(CFBundleRef, CFStringRef);
+static void *(*pCFBundleGetFunctionPointerForName)(CFBundleRef, CFStringRef);
+static CFTypeRef (*pLSGetCurrentApplicationASN)(void);
+static OSStatus (*pLSSetApplicationInformationItem)(int,
+													CFTypeRef,
+													CFStringRef,
+													CFStringRef,
+													CFDictionaryRef*);
+static CFBundleRef launch_services_bundle;
+static CFStringRef* display_name_key;
+static CFDictionaryRef (*pCFBundleGetInfoDictionary)(CFBundleRef);
+static CFBundleRef (*pCFBundleGetMainBundle)(void);
+static CFBundleRef hi_services_bundle;
+static OSStatus (*pSetApplicationIsDaemon)(int);
+static CFDictionaryRef (*pLSApplicationCheckIn)(int, CFDictionaryRef);
+static void (*pLSSetApplicationLaunchServicesServerConnectionStatus)(uint64_t,
+																	 void*);
+#define APPLE_S(s) pCFStringCreateWithCString(NULL, (s), kCFStringEncodingUTF8)
+/* Dlfunc handles */
+struct rspamd_osx_handles {
+	gpointer application_services_handle;
+	gpointer core_foundation_handle;
+};
+
+static
+void rspamd_darwin_title_dtor (void *ud)
+{
+	struct rspamd_osx_handles *hdls = (struct rspamd_osx_handles *)ud;
+
+	if (hdls->core_foundation_handle != NULL) {
+		dlclose (hdls->core_foundation_handle);
 	}
 
-	memset (title_buffer, '\0', title_buffer_size);
+	if (hdls->application_services_handle != NULL) {
+		dlclose (hdls->application_services_handle);
+	}
+}
 
-	ssize_t written;
+static void
+rspamd_darwin_init_title (struct rspamd_main *rspamd_main)
+{
+	struct rspamd_osx_handles *hdls;
+	/* Assumed that pthreads are already linked */
+	*(void **)(&dynamic_pthread_setname_np) =
+			dlsym (RTLD_DEFAULT, "pthread_setname_np");
+
+	hdls = rspamd_mempool_alloc0 (rspamd_main->server_pool, sizeof (*hdls));
+
+	hdls->application_services_handle = dlopen("/System/Library/Frameworks/"
+										 "ApplicationServices.framework/"
+										 "Versions/A/ApplicationServices",
+			RTLD_LAZY | RTLD_LOCAL);
+	hdls->core_foundation_handle = dlopen("/System/Library/Frameworks/"
+									"CoreFoundation.framework/"
+									"Versions/A/CoreFoundation",
+			RTLD_LAZY | RTLD_LOCAL);
+
+	if (hdls->application_services_handle == NULL ||
+		hdls->core_foundation_handle == NULL) {
+		goto out;
+	}
 
-	if (fmt) {
-		ssize_t written2;
-		va_list ap;
+	/* Fill procedures via dlsym */
+	*(void **)(&pCFStringCreateWithCString) =
+			dlsym (hdls->core_foundation_handle, "CFStringCreateWithCString");
+	*(void **)(&pCFBundleGetBundleWithIdentifier) =
+			dlsym (hdls->core_foundation_handle, "CFBundleGetBundleWithIdentifier");
+	*(void **)(&pCFBundleGetDataPointerForName) =
+			dlsym (hdls->core_foundation_handle, "CFBundleGetDataPointerForName");
+	*(void **)(&pCFBundleGetFunctionPointerForName) =
+			dlsym (hdls->core_foundation_handle, "CFBundleGetFunctionPointerForName");
+
+	if (pCFStringCreateWithCString == NULL ||
+		pCFBundleGetBundleWithIdentifier == NULL ||
+		pCFBundleGetDataPointerForName == NULL ||
+		pCFBundleGetFunctionPointerForName == NULL) {
+		goto out;
+	}
 
-		written = snprintf (title_buffer,
-				title_buffer_size,
-				"%s: ",
-				title_progname);
-		if (written < 0 || (size_t) written >= title_buffer_size)
-			return -1;
+	launch_services_bundle =
+			pCFBundleGetBundleWithIdentifier(APPLE_S("com.apple.LaunchServices"));
 
-		va_start (ap, fmt);
-		written2 = vsnprintf (title_buffer + written,
-				title_buffer_size - written,
-				fmt,
-				ap);
-		va_end (ap);
-		if (written2 < 0 || (size_t) written2 >= title_buffer_size - written)
-			return -1;
+	if (launch_services_bundle == NULL) {
+		goto out;
 	}
-	else {
-		written = snprintf (title_buffer,
-				title_buffer_size,
-				"%s",
-				title_progname);
-		if (written < 0 || (size_t) written >= title_buffer_size)
-			return -1;
+
+	*(void **)(&pLSGetCurrentApplicationASN) =
+			pCFBundleGetFunctionPointerForName(launch_services_bundle,
+					APPLE_S("_LSGetCurrentApplicationASN"));
+
+	if (pLSGetCurrentApplicationASN == NULL) {
+		goto out;
 	}
 
-	written = strlen (title_buffer);
-	memset (title_buffer + written, '\0', title_buffer_size - written);
+	*(void **)(&pLSSetApplicationInformationItem) =
+			pCFBundleGetFunctionPointerForName(launch_services_bundle,
+					APPLE_S("_LSSetApplicationInformationItem"));
 
-	return 0;
-#endif
-}
+	if (pLSSetApplicationInformationItem == NULL) {
+		goto out;
+	}
 
-#if !(defined(DARWIN) || defined(SOLARIS) || defined(__APPLE__))
-static void
-rspamd_title_dtor (gpointer d)
-{
-	gchar **env = (gchar **)d;
-	guint i;
+	display_name_key = pCFBundleGetDataPointerForName(launch_services_bundle,
+			APPLE_S("_kLSDisplayNameKey"));
 
-	for (i = 0; env[i] != NULL; i++) {
-		g_free (env[i]);
+	if (display_name_key == NULL || *display_name_key == NULL) {
+		goto out;
 	}
 
-	g_free (env);
+	*(void **)(&pCFBundleGetInfoDictionary) = dlsym (hdls->core_foundation_handle,
+			"CFBundleGetInfoDictionary");
+	*(void **)(&pCFBundleGetMainBundle) = dlsym (hdls->core_foundation_handle,
+			"CFBundleGetMainBundle");
+
+	if (pCFBundleGetInfoDictionary == NULL || pCFBundleGetMainBundle == NULL) {
+		goto out;
+	}
+
+	/* Black 10.9 magic, to remove (Not responding) mark in Activity Monitor */
+	hi_services_bundle =
+			pCFBundleGetBundleWithIdentifier(APPLE_S("com.apple.HIServices"));
+
+	if (hi_services_bundle == NULL) {
+		goto out;
+	}
+
+	*(void **)(&pSetApplicationIsDaemon) = pCFBundleGetFunctionPointerForName(
+			hi_services_bundle,
+			APPLE_S("SetApplicationIsDaemon"));
+	*(void **)(&pLSApplicationCheckIn) = pCFBundleGetFunctionPointerForName(
+			launch_services_bundle,
+			APPLE_S("_LSApplicationCheckIn"));
+	*(void **)(&pLSSetApplicationLaunchServicesServerConnectionStatus) =
+			pCFBundleGetFunctionPointerForName(
+					launch_services_bundle,
+					APPLE_S("_LSSetApplicationLaunchServicesServerConnectionStatus"));
+
+	if (pSetApplicationIsDaemon == NULL ||
+		pLSApplicationCheckIn == NULL ||
+		pLSSetApplicationLaunchServicesServerConnectionStatus == NULL) {
+		goto out;
+	}
+
+	rspamd_mempool_add_destructor (rspamd_main->server_pool,
+			rspamd_darwin_title_dtor, hdls);
+
+	return;
+
+out:
+	rspamd_darwin_title_dtor (hdls);
 }
-#endif
 
-/*
-   It has to be _init function, because __attribute__((constructor))
-   functions gets called without arguments.
- */
+#endif
 
 gint
 init_title (struct rspamd_main *rspamd_main,
 		gint argc, gchar *argv[], gchar *envp[])
 {
-#if defined(DARWIN) || defined(SOLARIS) || defined(__APPLE__)
-	/* XXX: try to handle these OSes too */
-	return 0;
-#else
+#ifdef LINUX
 	gchar *begin_of_buffer = 0, *end_of_buffer = 0;
 	gint i;
 
@@ -936,10 +1055,99 @@ init_title (struct rspamd_main *rspamd_main,
 
 	rspamd_mempool_add_destructor (rspamd_main->server_pool,
 			rspamd_title_dtor, new_environ);
+#elif defined(__APPLE__)
+	rspamd_darwin_init_title (rspamd_main);
+#endif
 
 	return 0;
+}
+
+gint
+setproctitle (const gchar *fmt, ...)
+{
+#if defined(LINUX)
+	if (!title_buffer || !title_buffer_size) {
+		errno = ENOMEM;
+		return -1;
+	}
+
+	memset (title_buffer, '\0', title_buffer_size);
+
+	ssize_t written;
+
+	if (fmt) {
+		ssize_t written2;
+		va_list ap;
+
+		written = rspamd_snprintf (title_buffer,
+				title_buffer_size,
+				"%s: ",
+				title_progname);
+		if (written < 0 || (size_t) written >= title_buffer_size)
+			return -1;
+
+		va_start (ap, fmt);
+		written2 = rspamd_vsnprintf (title_buffer + written,
+				title_buffer_size - written,
+				fmt,
+				ap);
+		va_end (ap);
+		if (written2 < 0 || (size_t) written2 >= title_buffer_size - written)
+			return -1;
+	}
+	else {
+		written = rspamd_snprintf (title_buffer,
+				title_buffer_size,
+				"%s",
+				title_progname);
+		if (written < 0 || (size_t) written >= title_buffer_size)
+			return -1;
+	}
+
+	written = strlen (title_buffer);
+	memset (title_buffer + written, '\0', title_buffer_size - written);
+#elif defined(__APPLE__)
+	static gchar titlebuf[128];
+
+	va_list ap;
+	int r;
+	va_start (ap, fmt);
+	r = rspamd_snprintf (titlebuf, sizeof (titlebuf), "rspamd: ");
+	rspamd_vsnprintf (titlebuf + r, sizeof (titlebuf) - r, fmt, ap);
+	va_end (ap);
+
+	if (pSetApplicationIsDaemon != NULL && pSetApplicationIsDaemon (1) != noErr) {
+		CFTypeRef asn;
+		pLSSetApplicationLaunchServicesServerConnectionStatus (0, NULL);
+		pLSApplicationCheckIn (/* Magic value */ -2,
+				pCFBundleGetInfoDictionary (pCFBundleGetMainBundle()));
+		asn = pLSGetCurrentApplicationASN ();
+		pLSSetApplicationInformationItem (/* Magic value */ -2, asn,
+				*display_name_key, APPLE_S (titlebuf), NULL);
+	}
+
+	if (dynamic_pthread_setname_np != NULL) {
+		char namebuf[64];  /* MAXTHREADNAMESIZE */
+		rspamd_strlcpy (namebuf, titlebuf, sizeof(namebuf));
+		dynamic_pthread_setname_np (namebuf);
+	}
+#else
+	/* Last resort (usually broken, but eh...) */
+	GString *dest;
+	va_list ap;
+
+	dest = g_string_new ("");
+	va_start (ap, fmt);
+	rspamd_vprintf_gstring (dest, fmt, ap);
+	va_end (ap);
+
+	g_set_prgname (dest->str);
+	g_string_free (dest, TRUE);
+
 #endif
+	return 0;
 }
+
 #endif
 
 #ifndef HAVE_PIDFILE


More information about the Commits mailing list