Skip to content

Commit ca04c29

Browse files
authored
Revert "[core] Downgrade vendored setproctitle to 1.2.3 (#60185)" (#60361)
Signed-off-by: joshlee <joshlee@anyscale.com>
1 parent 661f481 commit ca04c29

8 files changed

Lines changed: 295 additions & 58 deletions

File tree

src/ray/thirdparty/setproctitle/BUILD.bazel

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@ load("//bazel:ray.bzl", "ray_cc_library")
33
ray_cc_library(
44
name = "setproctitle",
55
srcs = glob(["spt*.c"]) + select({
6+
"@platforms//os:macos": ["darwin_set_process_name.c"],
67
"//conditions:default": [],
78
}),
89
hdrs = glob(["spt*.h"]) + ["c.h"] + select({
10+
"@platforms//os:macos": ["darwin_set_process_name.h"],
911
"//conditions:default": [],
1012
}),
1113
deps = ["@local_config_python//:python_headers"],
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
Currently vendored `setproctitle` version is 1.2.3
1+
Currently vendored `setproctitle` version is 1.3.6
22
The Cython code that exposes the C library to Python is setproctitle.pxd and setproctitle.pxi
33

44
Instructions to upgrade `setproctitle`:
55

6-
- pip download setproctitle==1.2.3 --no-binary=:all: --no-deps
7-
- tar xzvf setproctitle-1.2.3.tar.gz
8-
- mv setproctitle-1.2.3/src src/ray/thirdparty/setproctitle/
6+
- pip download setproctitle==1.3.6 --no-binary=:all: --no-deps
7+
- tar xzvf setproctitle-1.3.6.tar.gz
8+
- mv setproctitle-1.3.6/src src/ray/thirdparty/setproctitle/

src/ray/thirdparty/setproctitle/c.h

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,9 @@
1212

1313
#include "spt_config.h"
1414

15-
#ifndef __cplusplus
16-
17-
#ifndef bool
18-
typedef char bool;
19-
#endif
20-
21-
#ifndef true
22-
#define true ((bool) 1)
23-
#endif
24-
25-
#ifndef false
26-
#define false ((bool) 0)
15+
#if !defined(__cplusplus) && (!defined(__STDC_VERSION__) || __STDC_VERSION__ <= 201710L)
16+
#include <stdbool.h>
2717
#endif
28-
#endif /* not C++ */
2918

3019
#include <stddef.h>
3120

Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
/*
2+
3+
Set process title in a way compatible with Activity Monitor and other
4+
MacOS system tools.
5+
6+
Idea is borrowed from libuv (used by node.js)
7+
See https://github.com/libuv/libuv/blob/v1.x/src/unix/darwin-proctitle.c
8+
Implementation rewritten from scratch, fixing various libuv bugs among other things
9+
10+
*/
11+
12+
#include <CoreFoundation/CoreFoundation.h>
13+
14+
#include <dlfcn.h>
15+
#include <pthread.h>
16+
17+
#include "darwin_set_process_name.h"
18+
19+
#define DONE_IF(cond) if (cond) goto done;
20+
21+
/* Undocumented Launch Services functions */
22+
typedef enum {
23+
kLSDefaultSessionID = -2,
24+
} LSSessionID;
25+
CFTypeRef LSGetCurrentApplicationASN(void);
26+
OSStatus LSSetApplicationInformationItem(LSSessionID, CFTypeRef, CFStringRef, CFStringRef, CFDictionaryRef*);
27+
CFDictionaryRef LSApplicationCheckIn(LSSessionID, CFDictionaryRef);
28+
void LSSetApplicationLaunchServicesServerConnectionStatus(uint64_t, void *);
29+
30+
typedef struct {
31+
void * application_services_handle;
32+
33+
CFBundleRef launch_services_bundle;
34+
typeof(LSGetCurrentApplicationASN) * pLSGetCurrentApplicationASN;
35+
typeof(LSSetApplicationInformationItem) * pLSSetApplicationInformationItem;
36+
typeof(LSApplicationCheckIn) * pLSApplicationCheckIn;
37+
typeof(LSSetApplicationLaunchServicesServerConnectionStatus) * pLSSetApplicationLaunchServicesServerConnectionStatus;
38+
39+
CFStringRef * display_name_key_ptr;
40+
41+
} launch_services_t;
42+
43+
static bool launch_services_init(launch_services_t * it) {
44+
enum {
45+
has_nothing,
46+
has_application_services_handle
47+
} state = has_nothing;
48+
bool ret = false;
49+
50+
it->application_services_handle = dlopen("/System/Library/Frameworks/"
51+
"ApplicationServices.framework/"
52+
"Versions/Current/ApplicationServices",
53+
RTLD_LAZY | RTLD_LOCAL);
54+
DONE_IF(!it->application_services_handle);
55+
++state;
56+
57+
it->launch_services_bundle = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.LaunchServices"));
58+
DONE_IF(!it->launch_services_bundle);
59+
60+
#define LOAD_METHOD(name) \
61+
*(void **)(&it->p ## name ) = \
62+
CFBundleGetFunctionPointerForName(it->launch_services_bundle, CFSTR("_" #name)); \
63+
DONE_IF(!it->p ## name);
64+
65+
LOAD_METHOD(LSGetCurrentApplicationASN)
66+
LOAD_METHOD(LSSetApplicationInformationItem)
67+
LOAD_METHOD(LSApplicationCheckIn)
68+
LOAD_METHOD(LSSetApplicationLaunchServicesServerConnectionStatus)
69+
70+
#undef LOAD_METHOD
71+
72+
it->display_name_key_ptr =
73+
CFBundleGetDataPointerForName(it->launch_services_bundle, CFSTR("_kLSDisplayNameKey"));
74+
DONE_IF(!it->display_name_key_ptr || !*it->display_name_key_ptr);
75+
76+
ret = true;
77+
78+
done:
79+
switch(state) {
80+
case has_application_services_handle: if (!ret) dlclose(it->application_services_handle);
81+
case has_nothing: ;
82+
}
83+
return ret;
84+
}
85+
86+
static inline void launch_services_destroy(launch_services_t * it) {
87+
dlclose(it->application_services_handle);
88+
}
89+
90+
static bool launch_services_set_process_title(const launch_services_t * it, const char * title) {
91+
92+
enum {
93+
has_nothing,
94+
has_cf_title
95+
} state = has_nothing;
96+
bool ret = false;
97+
98+
static bool checked_in = false;
99+
100+
CFTypeRef asn;
101+
CFStringRef cf_title;
102+
CFDictionaryRef info_dict;
103+
CFMutableDictionaryRef mutable_info_dict;
104+
CFStringRef LSUIElement_key;
105+
106+
if (!checked_in) {
107+
it->pLSSetApplicationLaunchServicesServerConnectionStatus(0, NULL);
108+
109+
// See https://github.com/dvarrazzo/py-setproctitle/issues/143
110+
// We need to set LSUIElement (https://developer.apple.com/documentation/bundleresources/information-property-list/lsuielement)
111+
// key to true to avoid macOS > 15 displaying the Dock icon.
112+
info_dict = CFBundleGetInfoDictionary(CFBundleGetMainBundle());
113+
mutable_info_dict = CFDictionaryCreateMutableCopy(NULL, 0, info_dict);
114+
LSUIElement_key = CFStringCreateWithCString(NULL, "LSUIElement", kCFStringEncodingUTF8);
115+
CFDictionaryAddValue(mutable_info_dict, LSUIElement_key, kCFBooleanTrue);
116+
CFRelease(LSUIElement_key);
117+
118+
it->pLSApplicationCheckIn(kLSDefaultSessionID, mutable_info_dict);
119+
CFRelease(mutable_info_dict);
120+
121+
checked_in = true;
122+
}
123+
124+
asn = it->pLSGetCurrentApplicationASN();
125+
DONE_IF(!asn);
126+
127+
cf_title = CFStringCreateWithCString(NULL, title, kCFStringEncodingUTF8);
128+
DONE_IF(!cf_title);
129+
++state;
130+
DONE_IF(it->pLSSetApplicationInformationItem(kLSDefaultSessionID,
131+
asn,
132+
*it->display_name_key_ptr,
133+
cf_title,
134+
NULL) != noErr);
135+
ret = true;
136+
done:
137+
switch(state) {
138+
case has_cf_title: CFRelease(cf_title);
139+
case has_nothing: ;
140+
}
141+
142+
return ret;
143+
}
144+
145+
static bool darwin_pthread_setname_np(const char* name) {
146+
char namebuf[64]; /* MAXTHREADNAMESIZE according to libuv */
147+
148+
strncpy(namebuf, name, sizeof(namebuf) - 1);
149+
namebuf[sizeof(namebuf) - 1] = '\0';
150+
151+
return (pthread_setname_np(namebuf) != 0);
152+
}
153+
154+
155+
bool darwin_set_process_title(const char * title) {
156+
157+
enum {
158+
has_nothing,
159+
has_launch_services
160+
} state = has_nothing;
161+
bool ret = false;
162+
163+
launch_services_t launch_services;
164+
165+
DONE_IF(!launch_services_init(&launch_services));
166+
++state;
167+
168+
DONE_IF(!launch_services_set_process_title(&launch_services, title));
169+
170+
(void)darwin_pthread_setname_np(title);
171+
172+
ret = true;
173+
174+
done:
175+
switch(state) {
176+
case has_launch_services: launch_services_destroy(&launch_services);
177+
case has_nothing: ;
178+
}
179+
180+
return ret;
181+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#ifndef HEADER_DARWIN_SET_PROCESS_NAME_H_INCLUDED
2+
#define HEADER_DARWIN_SET_PROCESS_NAME_H_INCLUDED
3+
4+
#include "spt_config.h"
5+
6+
#include <stdbool.h>
7+
8+
HIDDEN bool darwin_set_process_title(const char * title);
9+
10+
#endif

src/ray/thirdparty/setproctitle/setproctitle.c

Lines changed: 40 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,6 @@
2525

2626
/* ----------------------------------------------------- */
2727

28-
static PyObject *spt_version;
29-
30-
3128
static char spt_setproctitle__doc__[] =
3229
"setproctitle(title) -- Change the process title."
3330
;
@@ -38,17 +35,18 @@ spt_setproctitle(PyObject *self, PyObject *args, PyObject *kwargs)
3835
const char *title = NULL;
3936
static char *kwlist[] = {"title", NULL};
4037

41-
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", kwlist, &title))
38+
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", kwlist, &title)) {
39+
spt_debug("failed to parse tuple and keywords");
4240
return NULL;
43-
44-
/* Initialize the process title */
45-
if (0 <= spt_setup()) {
46-
set_ps_display(title, true);
4741
}
48-
else {
42+
43+
if (spt_setup() < 0) {
4944
spt_debug("failed to initialize setproctitle");
5045
}
5146

47+
/* Initialize the process title */
48+
set_ps_display(title, true);
49+
5250
Py_RETURN_NONE;
5351
}
5452

@@ -63,7 +61,10 @@ spt_getproctitle(PyObject *self, PyObject *args)
6361
size_t tlen;
6462
const char *title;
6563

66-
spt_setup();
64+
if (spt_setup() < 0) {
65+
spt_debug("failed to initialize setproctitle");
66+
}
67+
6768
title = get_ps_display(&tlen);
6869

6970
return Py_BuildValue("s#", title, (int)tlen);
@@ -80,8 +81,10 @@ spt_setthreadtitle(PyObject *self, PyObject *args, PyObject *kwargs)
8081
const char *title = NULL;
8182
static char *kwlist[] = {"title", NULL};
8283

83-
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", kwlist, &title))
84+
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", kwlist, &title)) {
85+
spt_debug("failed to parse tuple and keywords");
8486
return NULL;
87+
}
8588

8689
set_thread_title(title);
8790

@@ -103,6 +106,27 @@ spt_getthreadtitle(PyObject *self, PyObject *args)
103106
return Py_BuildValue("s", title);
104107
}
105108

109+
/* Module initialization function */
110+
111+
static int
112+
spt_exec(PyObject *m)
113+
{
114+
spt_debug("module init");
115+
return 0;
116+
}
117+
118+
/* List of slots defined in the module */
119+
120+
static PyModuleDef_Slot spt_slots[] = {
121+
{Py_mod_exec, spt_exec},
122+
#if PY_VERSION_HEX >= 0x030c0000
123+
{Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
124+
#endif
125+
#if PY_VERSION_HEX >= 0x030d0000
126+
{Py_mod_gil, Py_MOD_GIL_NOT_USED},
127+
#endif
128+
{0, NULL}
129+
};
106130

107131
/* List of methods defined in the module */
108132

@@ -139,33 +163,18 @@ static char setproctitle_module_documentation[] =
139163

140164
static struct PyModuleDef moduledef = {
141165
PyModuleDef_HEAD_INIT,
142-
"setproctitle",
166+
"_setproctitle",
143167
setproctitle_module_documentation,
144-
-1,
168+
0,
145169
spt_methods,
146-
NULL,
170+
spt_slots,
147171
NULL,
148172
NULL,
149173
NULL
150174
};
151175

152176
PyMODINIT_FUNC
153-
PyInit_setproctitle(void)
177+
PyInit__setproctitle(void)
154178
{
155-
PyObject *m, *d;
156-
157-
spt_debug("module init");
158-
159-
/* Create the module and add the functions */
160-
m = PyModule_Create(&moduledef);
161-
if (m == NULL) { goto exit; }
162-
163-
/* Add version string to the module*/
164-
d = PyModule_GetDict(m);
165-
spt_version = Py_BuildValue("s", xstr(SPT_VERSION));
166-
PyDict_SetItemString(d, "__version__", spt_version);
167-
168-
exit:
169-
return m;
179+
return PyModuleDef_Init(&moduledef);
170180
}
171-

0 commit comments

Comments
 (0)