On Fri, 11 Nov 2016 21:14:37 +0000, Jun Wu wrote:
> # HG changeset patch
> # User Jun Wu <qu...@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
_______________________________________________
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel

Reply via email to