Add setproctitle_fast(3) for frequent callers.

Some applications, notably PostgreSQL, want to call setproctitle()
very often.  It's slow.  Provide an alternative cheap way of updating
process titles without making any syscalls, instead requiring other
processes (top, ps etc) to do a bit more work to retrieve the data.
This uses a pre-existing code path inherited from ancient BSD, which
always did it that way.

Submitted by:	Thomas Munro
MFC after:	2 weeks
Differential revision:	https://reviews.freebsd.org/D16111
This commit is contained in:
Konstantin Belousov 2018-07-04 13:31:16 +00:00
parent 4cb2adf3f8
commit 78f89679fc
3 changed files with 69 additions and 21 deletions

View File

@ -419,6 +419,7 @@ FBSD_1.5 {
scandir;
scandir_b;
sem_clockwait_np;
setproctitle_fast;
};
FBSDprivate_1.0 {

View File

@ -20,7 +20,7 @@
.\" $FreeBSD$
.\"
.\" The following requests are required for all man pages.
.Dd December 16, 1995
.Dd July 4, 2018
.Dt SETPROCTITLE 3
.Os
.Sh NAME
@ -31,12 +31,20 @@
.In unistd.h
.Ft void
.Fn setproctitle "const char *fmt" "..."
.Ft void
.Fn setproctitle_fast "const char *fmt" "..."
.Sh DESCRIPTION
The
.Fn setproctitle
library routine sets the process title that appears on the
.Xr ps 1
command.
The
.Fn setproctitle_fast
variant is optimized for high frequency updates, but may make the
.Xr ps 1
command slightly slower by not updating the kernel cache of the program
arguments.
.Pp
The title is set from the executable's name, followed by the
result of a
@ -96,6 +104,10 @@ The
function
first appeared in
.Fx 2.2 .
The
.Fn setproctitle_fast
function first appeared in
.Fx 12 .
Other operating systems have
similar functions.
.Sh AUTHORS

View File

@ -55,8 +55,8 @@ struct old_ps_strings {
#define SPT_BUFSIZE 2048 /* from other parts of sendmail */
void
setproctitle(const char *fmt, ...)
static char *
setproctitle_internal(const char *fmt, va_list ap)
{
static struct ps_strings *ps_strings;
static char *buf = NULL;
@ -67,27 +67,23 @@ setproctitle(const char *fmt, ...)
char **nargvp;
int nargc;
int i;
va_list ap;
size_t len;
unsigned long ul_ps_strings;
int oid[4];
if (buf == NULL) {
buf = malloc(SPT_BUFSIZE);
if (buf == NULL)
return;
return (NULL);
nargv[0] = buf;
}
if (obuf == NULL ) {
obuf = malloc(SPT_BUFSIZE);
if (obuf == NULL)
return;
return (NULL);
*obuf = '\0';
}
va_start(ap, fmt);
if (fmt) {
buf[SPT_BUFSIZE - 1] = '\0';
@ -114,22 +110,13 @@ setproctitle(const char *fmt, ...)
kbuf = obuf;
} else
/* Nothing to restore */
return;
va_end(ap);
/* Set the title into the kernel cached command line */
oid[0] = CTL_KERN;
oid[1] = KERN_PROC;
oid[2] = KERN_PROC_ARGS;
oid[3] = getpid();
sysctl(oid, 4, 0, 0, kbuf, strlen(kbuf) + 1);
return (NULL);
if (ps_strings == NULL) {
len = sizeof(ul_ps_strings);
if (sysctlbyname("kern.ps_strings", &ul_ps_strings, &len, NULL,
0) == -1)
return;
return (NULL);
ps_strings = (struct ps_strings *)ul_ps_strings;
}
@ -138,7 +125,7 @@ setproctitle(const char *fmt, ...)
* Should not happen.
*/
if (ps_strings->ps_argvstr == NULL)
return;
return (NULL);
/* style #3 */
if (oargc == -1) {
@ -167,4 +154,52 @@ setproctitle(const char *fmt, ...)
}
ps_strings->ps_nargvstr = nargc;
ps_strings->ps_argvstr = nargvp;
return (nargvp[0]);
}
static int fast_update = 0;
void
setproctitle_fast(const char *fmt, ...)
{
va_list ap;
char *buf;
int oid[4];
va_start(ap, fmt);
buf = setproctitle_internal(fmt, ap);
va_end(ap);
if (buf && !fast_update) {
/* Tell the kernel to start looking in user-space */
oid[0] = CTL_KERN;
oid[1] = KERN_PROC;
oid[2] = KERN_PROC_ARGS;
oid[3] = getpid();
sysctl(oid, 4, 0, 0, "", 0);
fast_update = 1;
}
}
void
setproctitle(const char *fmt, ...)
{
va_list ap;
char *buf;
int oid[4];
va_start(ap, fmt);
buf = setproctitle_internal(fmt, ap);
va_end(ap);
if (buf != NULL) {
/* Set the title into the kernel cached command line */
oid[0] = CTL_KERN;
oid[1] = KERN_PROC;
oid[2] = KERN_PROC_ARGS;
oid[3] = getpid();
sysctl(oid, 4, 0, 0, buf, strlen(buf) + 1);
fast_update = 0;
}
}