Get IPC working
This commit is contained in:
parent
bf09c33b99
commit
7deb68de61
4 changed files with 50 additions and 14 deletions
|
|
@ -18,7 +18,8 @@
|
|||
from .session import create_session
|
||||
from .tabs import SpecialWindow, TabManager
|
||||
from .utils import (
|
||||
get_primary_selection, open_url, safe_print, set_primary_selection
|
||||
get_primary_selection, open_url, safe_print, set_primary_selection,
|
||||
single_instance
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -61,9 +62,13 @@ def __init__(self, os_window_id, opts, args):
|
|||
self.os_window_map = {}
|
||||
self.cursor_blinking = True
|
||||
self.shutting_down = False
|
||||
talk_fd = getattr(single_instance, 'socket', None)
|
||||
talk_fd = -1 if talk_fd is None else talk_fd.fileno()
|
||||
self.child_monitor = ChildMonitor(
|
||||
self.on_child_death,
|
||||
DumpCommands(args) if args.dump_commands or args.dump_bytes else None)
|
||||
DumpCommands(args) if args.dump_commands or args.dump_bytes else None,
|
||||
talk_fd
|
||||
)
|
||||
set_boss(self)
|
||||
self.current_font_size = opts.font_size
|
||||
set_font_family(opts)
|
||||
|
|
@ -88,6 +93,12 @@ def add_child(self, window):
|
|||
self.child_monitor.add_child(window.id, window.child.pid, window.child.child_fd, window.screen)
|
||||
self.window_id_map[window.id] = window
|
||||
|
||||
def peer_msg_received(self, msg):
|
||||
import json
|
||||
msg = json.loads(msg.decode('utf-8'))
|
||||
if msg.get('cmd') == 'new_instance':
|
||||
print(msg['args'])
|
||||
|
||||
def on_child_death(self, window_id):
|
||||
window = self.window_id_map.pop(window_id, None)
|
||||
if window is None:
|
||||
|
|
|
|||
|
|
@ -223,9 +223,6 @@ join(ChildMonitor *self) {
|
|||
#define join_doc "join() -> Wait for the I/O thread to finish"
|
||||
int ret = pthread_join(self->io_thread, NULL);
|
||||
if (ret != 0) return PyErr_SetFromErrno(PyExc_OSError);
|
||||
if (self->talk_fd > -1) {
|
||||
if (pthread_join(self->talk_thread, NULL) != 0) return PyErr_SetFromErrno(PyExc_OSError);
|
||||
}
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
|
|
@ -341,10 +338,10 @@ parse_input(ChildMonitor *self) {
|
|||
}
|
||||
|
||||
if (UNLIKELY(self->messages_count)) {
|
||||
while(self->messages_count--) {
|
||||
Message *m = self->messages + self->messages_count;
|
||||
while(self->messages_count) {
|
||||
Message *m = self->messages + --self->messages_count;
|
||||
call_boss(peer_msg_received, "y#", m->data, m->sz);
|
||||
free(m->data);
|
||||
free(m->data); m->data = NULL; m->sz = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -928,14 +925,13 @@ io_loop(void *data) {
|
|||
|
||||
static inline void
|
||||
handle_peer(ChildMonitor *self, int s) {
|
||||
size_t bufsz = 1024;
|
||||
size_t bufsz = 0;
|
||||
char *buf = NULL;
|
||||
size_t buf_used = 0;
|
||||
if (buf == NULL) return;
|
||||
|
||||
while(true) {
|
||||
if (buf_used >= bufsz) {
|
||||
bufsz *= 2;
|
||||
bufsz = MAX(1024, bufsz) * 2;
|
||||
if (bufsz > 1024 * 1024) return;
|
||||
buf = realloc(buf, bufsz);
|
||||
if (buf == NULL) return;
|
||||
|
|
@ -951,7 +947,7 @@ handle_peer(ChildMonitor *self, int s) {
|
|||
}
|
||||
if (buf_used) {
|
||||
children_mutex(lock);
|
||||
ensure_space_for(self, messages, Message, self->messages_count + 1, messages_capacity, 16, false);
|
||||
ensure_space_for(self, messages, Message, self->messages_count + 1, messages_capacity, 16, true);
|
||||
Message *m = self->messages + self->messages_count++;
|
||||
m->data = buf; m->sz = buf_used;
|
||||
children_mutex(unlock);
|
||||
|
|
@ -969,7 +965,7 @@ talk_loop(void *data) {
|
|||
int peer = accept(self->talk_fd, NULL, NULL);
|
||||
if (peer == -1) {
|
||||
if (errno == EINTR) continue;
|
||||
perror("accept() on talk socket failed!");
|
||||
if (!self->shutting_down) perror("accept() on talk socket failed!");
|
||||
break;
|
||||
}
|
||||
handle_peer(self, peer);
|
||||
|
|
|
|||
21
kitty/cli.py
21
kitty/cli.py
|
|
@ -101,6 +101,27 @@ def option_parser():
|
|||
'Path to a file containing the startup session (tabs, windows, layout, programs)'
|
||||
)
|
||||
)
|
||||
a(
|
||||
'-1', '--single-instance',
|
||||
default=False,
|
||||
action='store_true',
|
||||
help=_(
|
||||
'If specified only a single instance of {0} will run. New invocations will'
|
||||
' instead create a new top-level window in the existing {0} instance. This'
|
||||
' allows {0} to share a single sprite cache on the GPU and also reduces'
|
||||
' startup time. You can also have groups of {0} instances by using the'
|
||||
' {1} option.'
|
||||
).format(appname, '--instance-group')
|
||||
)
|
||||
a(
|
||||
'--instance-group',
|
||||
default=None,
|
||||
help=_(
|
||||
'Used in combination with the --single-instance option. All {0} invocations'
|
||||
' with the same --instance-group will result in new windows being created'
|
||||
' in the first {0} instance with that group.'
|
||||
).format(appname)
|
||||
)
|
||||
a(
|
||||
'args',
|
||||
nargs=argparse.REMAINDER,
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@
|
|||
from .fonts.box_drawing import set_scale
|
||||
from .utils import (
|
||||
detach, end_startup_notification, get_logical_dpi,
|
||||
init_startup_notification
|
||||
init_startup_notification, single_instance
|
||||
)
|
||||
from .window import load_shader_programs
|
||||
|
||||
|
|
@ -129,6 +129,14 @@ def main():
|
|||
from kitty.client import main
|
||||
main(args.replay_commands)
|
||||
return
|
||||
if args.single_instance:
|
||||
is_first = single_instance(args.instance_group)
|
||||
if not is_first:
|
||||
import json
|
||||
data = {'cmd': 'new_instance', 'args': tuple(sys.argv)}
|
||||
data = json.dumps(data, ensure_ascii=False).encode('utf-8')
|
||||
single_instance.socket.sendall(data)
|
||||
return
|
||||
config = args.config or (defconf, )
|
||||
overrides = (a.replace('=', ' ', 1) for a in args.override or ())
|
||||
opts = load_config(*config, overrides=overrides)
|
||||
|
|
|
|||
Loading…
Reference in a new issue