[PATCH 2 of 2] osutil: implement setprocname to set process title for some platforms
Yuya Nishihara
yuya at tcha.org
Sun Nov 13 09:18:10 EST 2016
On Fri, 11 Nov 2016 21:14:37 +0000, Jun Wu wrote:
> # HG changeset patch
> # User Jun Wu <quark at fb.com>
> # Date 1478898677 0
> # Fri Nov 11 21:11:17 2016 +0000
> # Node ID 4ccb6bcaf25a741d3a0d8abd6c674573ef76069a
> # Parent 98761d64eaaf67f3bdb99f3f80a57910e2624b78
> # Available At https://bitbucket.org/quark-zju/hg-draft
> # hg pull https://bitbucket.org/quark-zju/hg-draft -r 4ccb6bcaf25a
> osutil: implement setprocname to set process title for some platforms
Seems fine. We can't guarantee argv[i] is null terminated for all i, but
that seems less dangerous since the last argv[i] always has '\0'.
A few nits.
> --- a/mercurial/osutil.c
> +++ b/mercurial/osutil.c
> @@ -728,4 +728,59 @@ bail:
>
> #endif /* CMSG_LEN */
> +
> +/* Check what setprocname method we can use:
> + * a. use setproctitle if it's available - works in FreeBSD
> + * b. rewrite **argv buffer in place - works in Linux and OS X
> + * Note: for "b.", we need Python 2, because Python 3's Py_GetArgcArgv returns
> + * the copied wchar_t **argv, not the original char **argv. */
> +#if defined(HAVE_SETPROCTITLE)
> +#define setprocname_method 'a'
> +#elif (defined(__linux__) || defined(__APPLE__)) && PY_MAJOR_VERSION == 2
> +#define setprocname_method 'b'
> +#else
> +#undef setprocname_method
> +#endif
Lowercase macro name and char-type value seem not common. Can you change them
to old-school macros such as SETPROCNAME_USE_SETPROCTITLE?
> +#ifdef setprocname_method
> +static PyObject *setprocname(PyObject *self, PyObject *args)
> +{
> + const char *name = NULL;
> + if (!PyArg_ParseTuple(args, "s", &name))
> + return NULL;
> +
> +#if 'a' == setprocname_method
> + setproctitle("%s", name);
> +#elif 'b' == setprocname_method
> + static char *argvstart = NULL;
> + static size_t argvsize = 0;
Strictly speaking, these declarations should be moved to the block head. (But
almost all modern compilers but for MSVC would allow mixed declarations.)
> + if (argvstart == NULL) {
> + int argc = 0, i;
> + char **argv = NULL;
> + extern void Py_GetArgcArgv(int *argc, char ***argv);
> + Py_GetArgcArgv(&argc, &argv);
> +
> + /* Check the memory we can use. Typically, argv[i] and
> + * argv[i+1] are separated by a NULL character. */
> + if (argc > 0) {
> + argvstart = argv[0];
> + argvsize = strlen(argv[0]) + 1;
> + for (i = 1; i < argc; ++i) {
> + if (argv[i] == argvstart + argvsize)
> + argvsize += strlen(argv[i]) + 1;
> + }
> + }
Perhaps this loop can start with argvstart = argv[0], argvsize = 0, i = 0.
> + }
> +
> + if (argvstart && argvsize > 1) {
> + int n = snprintf(argvstart, argvsize - 1, "%s", name);
IIRC, snprintf() takes size including the last null byte and null termination
is guaranteed.
> + if (n >= 0 && (size_t)n < argvsize)
> + memset(argvstart + n, 0, argvsize - n);
> + }
> +#endif
More information about the Mercurial-devel
mailing list