aix: enable uv_get/set_process_title

This patch enables querying and setting the process title on AIX.
libuv takes ownership of the memory for argv and returns a deep copy
of the array and its contents.
It also enables the process_title test case.

The process title can be changed on AIX but is handled differently
to Linux/Mac. Commands like ps read the original argv array passed
to the process instead of the memory at argv[0]. To change the process
title we need to update argv[0] to point at a new string and set
argv[1] to NULL (if it exists). This means the process title
can be set to a string of any length.

PR-URL: https://github.com/libuv/libuv/pull/1187
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: Santiago Gimeno <santiago.gimeno@gmail.com>
This commit is contained in:
Howard Hellyer 2017-01-12 04:50:17 -05:00 committed by Santiago Gimeno
parent c5bb773bdd
commit d6427e4beb
No known key found for this signature in database
GPG Key ID: F28C3C8DA33C03BE
3 changed files with 83 additions and 4 deletions

View File

@ -192,7 +192,11 @@ API
.. c:function:: int uv_set_process_title(const char* title)
Sets the current process title.
Sets the current process title. On platforms with a fixed size buffer for the
process title the contents of `title` will be copied to the buffer and
truncated if larger than the available space. Other platforms will return
`UV_ENOMEM` if they cannot allocate enough space to duplicate the contents of
`title`.
.. c:function:: int uv_resident_set_memory(size_t* rss)

View File

@ -64,6 +64,11 @@
#define RDWR_BUF_SIZE 4096
#define EQ(a,b) (strcmp(a,b) == 0)
static void* args_mem = NULL;
static char** process_argv = NULL;
static int process_argc = 0;
static char* process_title_ptr = NULL;
int uv__platform_loop_init(uv_loop_t* loop) {
loop->fs_fd = -1;
@ -881,24 +886,94 @@ void uv__fs_event_close(uv_fs_event_t* handle) {
char** uv_setup_args(int argc, char** argv) {
return argv;
char** new_argv;
size_t size;
char* s;
int i;
if (argc <= 0)
return argv;
/* Save the original pointer to argv.
* AIX uses argv to read the process name.
* (Not the memory pointed to by argv[0..n] as on Linux.)
*/
process_argv = argv;
process_argc = argc;
/* Calculate how much memory we need for the argv strings. */
size = 0;
for (i = 0; i < argc; i++)
size += strlen(argv[i]) + 1;
/* Add space for the argv pointers. */
size += (argc + 1) * sizeof(char*);
new_argv = uv__malloc(size);
if (new_argv == NULL)
return argv;
args_mem = new_argv;
/* Copy over the strings and set up the pointer table. */
s = (char*) &new_argv[argc + 1];
for (i = 0; i < argc; i++) {
size = strlen(argv[i]) + 1;
memcpy(s, argv[i], size);
new_argv[i] = s;
s += size;
}
new_argv[i] = NULL;
return new_argv;
}
int uv_set_process_title(const char* title) {
char* new_title;
/* We cannot free this pointer when libuv shuts down,
* the process may still be using it.
*/
new_title = uv__strdup(title);
if (new_title == NULL)
return -ENOMEM;
/* If this is the first time this is set,
* don't free and set argv[1] to NULL.
*/
if (process_title_ptr != NULL)
uv__free(process_title_ptr);
process_title_ptr = new_title;
process_argv[0] = process_title_ptr;
if (process_argc > 1)
process_argv[1] = NULL;
return 0;
}
int uv_get_process_title(char* buffer, size_t size) {
size_t len;
len = strlen(process_argv[0]);
if (buffer == NULL || size == 0)
return -EINVAL;
else if (size <= len)
return -ENOBUFS;
memcpy(buffer, process_argv[0], len + 1);
buffer[0] = '\0';
return 0;
}
UV_DESTRUCTOR(static void free_args_mem(void)) {
uv__free(args_mem); /* Keep valgrind happy. */
args_mem = NULL;
}
int uv_resident_set_memory(size_t* rss) {
char pp[64];
psinfo_t psinfo;

View File

@ -60,7 +60,7 @@ static void uv_get_process_title_edge_cases() {
TEST_IMPL(process_title) {
#if defined(__sun) || defined(_AIX) || defined(__MVS__)
#if defined(__sun) || defined(__MVS__)
RETURN_SKIP("uv_(get|set)_process_title is not implemented.");
#else
/* Check for format string vulnerabilities. */