Fix exec in prewarm forked process sometimes inheriting env vars from grandparent process
This commit is contained in:
parent
1ba027c277
commit
89a0c04d19
@ -181,8 +181,26 @@ spawn(PyObject *self UNUSED, PyObject *args) {
|
||||
return PyLong_FromLong(pid);
|
||||
}
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <crt_externs.h>
|
||||
#else
|
||||
extern char **environ;
|
||||
#endif
|
||||
|
||||
static PyObject*
|
||||
clearenv_py(PyObject *self UNUSED, PyObject *args UNUSED) {
|
||||
#ifdef __APPLE__
|
||||
char **e = *_NSGetEnviron();
|
||||
if (e) *e = NULL;
|
||||
#else
|
||||
if (environ) *environ = NULL;
|
||||
#endif
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static PyMethodDef module_methods[] = {
|
||||
METHODB(spawn, METH_VARARGS),
|
||||
{"clearenv", clearenv_py, METH_NOARGS, ""},
|
||||
{NULL, NULL, 0, NULL} /* Sentinel */
|
||||
};
|
||||
|
||||
|
||||
@ -1485,3 +1485,4 @@ class SingleKey:
|
||||
|
||||
def set_use_os_log(yes: bool) -> None: ...
|
||||
def get_docs_ref_map() -> bytes: ...
|
||||
def clearenv() -> None: ...
|
||||
|
||||
@ -24,9 +24,9 @@ from typing import (
|
||||
from kitty.constants import kitty_exe, running_in_kitty
|
||||
from kitty.entry_points import main as main_entry_point
|
||||
from kitty.fast_data_types import (
|
||||
CLD_EXITED, CLD_KILLED, CLD_STOPPED, get_options, install_signal_handlers,
|
||||
read_signals, remove_signal_handlers, safe_pipe, set_options,
|
||||
set_use_os_log
|
||||
CLD_EXITED, CLD_KILLED, CLD_STOPPED, clearenv, get_options,
|
||||
install_signal_handlers, read_signals, remove_signal_handlers, safe_pipe,
|
||||
set_options, set_use_os_log
|
||||
)
|
||||
from kitty.options.types import Options
|
||||
from kitty.shm import SharedMemory
|
||||
@ -293,6 +293,13 @@ def child_main(cmd: Dict[str, Any], ready_fd: int = -1, prewarm_type: str = 'dir
|
||||
env = cmd.get('env')
|
||||
if env is not None:
|
||||
os.environ.clear()
|
||||
# os.environ.clear() does not delete all existing env vars from the
|
||||
# libc environ pointer in some circumstances, I havent figured out
|
||||
# which exactly. Presumably there is something that alters the
|
||||
# libc environ pointer?? The environ pointer is used by os.exec and
|
||||
# therefore by subprocess and friends, so we need to ensure it is
|
||||
# cleared.
|
||||
clearenv()
|
||||
os.environ.update(env)
|
||||
argv = cmd.get('argv')
|
||||
if argv:
|
||||
|
||||
@ -28,13 +28,15 @@ class Prewarm(BaseTest):
|
||||
|
||||
cwd = tempfile.gettempdir()
|
||||
env = {'TEST_ENV_PASS': 'xyz'}
|
||||
cols = 117
|
||||
cols = 317
|
||||
stdin_data = 'from_stdin'
|
||||
pty = self.create_pty(cols=cols)
|
||||
ttyname = os.ttyname(pty.slave_fd)
|
||||
opts = get_options()
|
||||
opts.config_overrides = 'font_family prewarm',
|
||||
os.environ['SHOULD_NOT_BE_PRESENT'] = '1'
|
||||
p = fork_prewarm_process(opts, use_exec=True)
|
||||
del os.environ['SHOULD_NOT_BE_PRESENT']
|
||||
if p is None:
|
||||
return
|
||||
p.take_from_worker_fd(create_file=True)
|
||||
@ -44,7 +46,7 @@ import os, json; from kitty.utils import *; from kitty.fast_data_types import ge
|
||||
'ttyname': os.ttyname(sys.stdout.fileno()),
|
||||
'cols': read_screen_size().cols,
|
||||
'cwd': os.getcwd(),
|
||||
'env': os.environ.get('TEST_ENV_PASS'),
|
||||
'env': os.environ.copy(),
|
||||
'pid': os.getpid(),
|
||||
'font_family': get_options().font_family,
|
||||
'stdin': sys.stdin.read(),
|
||||
@ -59,7 +61,8 @@ import os, json; from kitty.utils import *; from kitty.fast_data_types import ge
|
||||
self.assertTrue(data['cterm'])
|
||||
self.ae(data['ttyname'], ttyname)
|
||||
self.ae(os.path.realpath(data['cwd']), os.path.realpath(cwd))
|
||||
self.ae(data['env'], env['TEST_ENV_PASS'])
|
||||
self.ae(data['env']['TEST_ENV_PASS'], env['TEST_ENV_PASS'])
|
||||
self.assertNotIn('SHOULD_NOT_BE_PRESENT', data['env'])
|
||||
self.ae(data['font_family'], 'prewarm')
|
||||
self.ae(int(p.from_worker.readline()), data['pid'])
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user