Get IPC working

This commit is contained in:
Kovid Goyal 2017-11-17 13:12:34 +05:30
parent bf09c33b99
commit 7deb68de61
No known key found for this signature in database
GPG key ID: 06BC317B515ACE7C
4 changed files with 50 additions and 14 deletions

View file

@ -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:

View file

@ -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);

View file

@ -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,

View file

@ -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)