Patchwork Remove 16-character limit on process title

login
register
mail settings
Submitter John Morrissey
Date Oct. 20, 2010, 7:10 p.m.
Message ID <20101020191035.GA5674@boost.horde.net>
Download mbox | patch
Permalink /patch/68466/
State New
Headers show

Comments

John Morrissey - Oct. 20, 2010, 7:10 p.m.
qemu uses prctl() to set its process title. I bumped up against prctl()'s
16-character limit recently, when adding process title support to
libvirt[1][2].

The attached patch overwrites argv instead. Linux seems to maintain the
length of the original args, even when the new args are shorter and
NULL-terminated, so the trailing whitespace in ps(1) output is probably
unavoidable. I've seen the same result with other daemons that overwrite
argv.

john

[1] https://www.redhat.com/archives/libvir-list/2010-October/msg00565.html
[2] http://libvirt.org/git/?p=libvirt.git;a=commit;h=c08c7b0143b8cdc542e5f4137623d412340c5cf2

Patch

diff --git a/os-posix.c b/os-posix.c
index 6321e99..4d85384 100644
--- a/os-posix.c
+++ b/os-posix.c
@@ -39,10 +39,6 @@ 
 #include "net/slirp.h"
 #include "qemu-options.h"
 
-#ifdef CONFIG_LINUX
-#include <sys/prctl.h>
-#endif
-
 static struct passwd *user_pwd;
 static const char *chroot_dir;
 static int daemonize;
@@ -145,20 +141,24 @@  char *os_find_datadir(const char *argv0)
 #undef SHARE_SUFFIX
 #undef BUILD_SUFFIX
 
-void os_set_proc_name(const char *s)
+void os_set_proc_name(int argc, char **argv, const char *name)
 {
-#if defined(PR_SET_NAME)
-    char name[16];
-    if (!s)
+#ifdef CONFIG_LINUX
+    char *last_argv_byte, *p;
+    int len, i;
+
+    if (!name)
         return;
-    name[sizeof(name) - 1] = 0;
-    strncpy(name, s, sizeof(name));
-    /* Could rewrite argv[0] too, but that's a bit more complicated.
-       This simple way is enough for `top'. */
-    if (prctl(PR_SET_NAME, name)) {
-        perror("unable to change process name");
-        exit(1);
-    }
+
+    last_argv_byte = argv[argc - 1] + strlen(argv[argc - 1]);
+
+    len = snprintf(argv[0], last_argv_byte - argv[0], "%s", name);
+
+    p = &argv[0][len];
+    while (p <= last_argv_byte)
+        *p++ = '\0';
+    for (i = 1; i < argc; ++i)
+        argv[i] = (char *) "";
 #else
     fprintf(stderr, "Change of process name not supported by your OS\n");
     exit(1);
diff --git a/qemu-os-posix.h b/qemu-os-posix.h
index ed5c058..b2e3b6a 100644
--- a/qemu-os-posix.h
+++ b/qemu-os-posix.h
@@ -31,7 +31,7 @@  static inline void os_host_main_loop_wait(int *timeout)
 }
 
 void os_set_line_buffering(void);
-void os_set_proc_name(const char *s);
+void os_set_proc_name(int argc, char **argv, const char *name);
 void os_setup_signal_handling(void);
 void os_daemonize(void);
 void os_setup_post(void);
diff --git a/qemu-os-win32.h b/qemu-os-win32.h
index c63778d..9653992 100644
--- a/qemu-os-win32.h
+++ b/qemu-os-win32.h
@@ -46,7 +46,8 @@  static inline void os_setup_signal_handling(void) {}
 static inline void os_daemonize(void) {}
 static inline void os_setup_post(void) {}
 void os_set_line_buffering(void);
-static inline void os_set_proc_name(const char *dummy) {}
+static inline void os_set_proc_name(int argc, char **argv,
+                                    const char *dummy) {}
 
 #if !defined(EPROTONOSUPPORT)
 # define EPROTONOSUPPORT EINVAL
diff --git a/vl.c b/vl.c
index df414ef..b82b0e8 100644
--- a/vl.c
+++ b/vl.c
@@ -1799,7 +1799,11 @@  static const QEMUOption *lookup_opt(int argc, char **argv,
         optarg = NULL;
     }
 
-    *poptarg = optarg;
+    if (optarg != NULL) {
+        *poptarg = qemu_strdup(optarg);
+    } else {
+        *poptarg = NULL;
+    }
     *poptind = optind;
 
     return popt;
@@ -1827,6 +1831,7 @@  int main(int argc, char **argv, char **envp)
     int tb_size;
     const char *pid_file = NULL;
     const char *incoming = NULL;
+    const char *process_name = NULL;
     int show_vnc_port = 0;
     int defconfig = 1;
 
@@ -2528,7 +2533,7 @@  int main(int argc, char **argv, char **envp)
 			    exit(1);
 			}
 			p += 8;
-			os_set_proc_name(p);
+			process_name = p;
 		     }	
 		 }	
                 break;
@@ -2754,6 +2759,8 @@  int main(int argc, char **argv, char **envp)
         exit(1);
     }
 
+    os_set_proc_name(argc, argv, process_name);
+
     if (kvm_allowed) {
         int ret = kvm_init(smp_cpus);
         if (ret < 0) {