Implement --listen-on option

This commit is contained in:
Kovid Goyal 2018-03-01 20:22:04 +05:30
parent 19e59d9575
commit 52d2b7b09e
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
3 changed files with 45 additions and 6 deletions

View File

@ -2,7 +2,9 @@
# vim:fileencoding=utf-8
# License: GPL v3 Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>
import atexit
import re
import socket
from functools import partial
from gettext import gettext as _
from weakref import WeakValueDictionary
@ -24,7 +26,8 @@ from .session import create_session
from .tabs import SpecialWindow, SpecialWindowInstance, TabManager
from .utils import (
end_startup_notification, get_primary_selection, init_startup_notification,
open_url, safe_print, set_primary_selection, single_instance
open_url, remove_socket_file, safe_print, set_primary_selection,
single_instance
)
@ -33,6 +36,29 @@ def initialize_renderer():
prerender()
def listen_on(spec):
protocol, rest = spec.split(':', 1)
socket_path = None
if protocol == 'unix':
family = socket.AF_UNIX
address = rest
if address.startswith('@') and len(address) > 1:
address = '\0' + address[1:]
else:
socket_path = address
elif protocol in ('tcp', 'tcp6'):
family = socket.AF_INET if protocol == 'tcp' else socket.AF_INET6
host, port = rest.rsplit(':', 1)
address = host, int(port)
else:
raise ValueError('Unknown protocol in --listen-on value: {}'.format(spec))
s = socket.socket(family)
atexit.register(remove_socket_file, s, socket_path)
s.bind(address)
s.listen()
return s.fileno()
class DumpCommands: # {{{
def __init__(self, args):
@ -70,10 +96,13 @@ class Boss:
self.shutting_down = False
talk_fd = getattr(single_instance, 'socket', None)
talk_fd = -1 if talk_fd is None else talk_fd.fileno()
listen_fd = -1
if opts.allow_remote_control and args.listen_on:
listen_fd = listen_on(args.listen_on)
self.child_monitor = ChildMonitor(
self.on_child_death,
DumpCommands(args) if args.dump_commands or args.dump_bytes else None,
talk_fd
talk_fd, listen_fd
)
set_boss(self)
self.current_font_size = opts.font_size

View File

@ -36,7 +36,7 @@ typedef struct {
bool shutting_down;
pthread_t io_thread, talk_thread;
int talk_fd;
int talk_fd, listen_fd;
Message *messages;
size_t messages_capacity, messages_count;
} ChildMonitor;
@ -120,11 +120,11 @@ static PyObject *
new(PyTypeObject *type, PyObject *args, PyObject UNUSED *kwds) {
ChildMonitor *self;
PyObject *dump_callback, *death_notify;
int talk_fd = -1;
int talk_fd = -1, listen_fd = -1;
int ret;
if (the_monitor) { PyErr_SetString(PyExc_RuntimeError, "Can have only a single ChildMonitor instance"); return NULL; }
if (!PyArg_ParseTuple(args, "OO|i", &death_notify, &dump_callback, &talk_fd)) return NULL;
if (!PyArg_ParseTuple(args, "OO|ii", &death_notify, &dump_callback, &talk_fd, &listen_fd)) return NULL;
if ((ret = pthread_mutex_init(&children_lock, NULL)) != 0) {
PyErr_Format(PyExc_RuntimeError, "Failed to create children_lock mutex: %s", strerror(ret));
return NULL;
@ -138,6 +138,7 @@ new(PyTypeObject *type, PyObject *args, PyObject UNUSED *kwds) {
if (siginterrupt(SIGTERM, false) != 0) return PyErr_SetFromErrno(PyExc_OSError);
self = (ChildMonitor *)type->tp_alloc(type, 0);
self->talk_fd = talk_fd;
self->listen_fd = listen_fd;
if (self == NULL) return PyErr_NoMemory();
self->death_notify = death_notify; Py_INCREF(death_notify);
if (dump_callback != Py_None) {
@ -191,7 +192,7 @@ static void send_response(int fd, const char *msg, size_t msg_sz);
static PyObject *
start(ChildMonitor *self) {
#define start_doc "start() -> Start the I/O thread"
if (self->talk_fd > -1) {
if (self->talk_fd > -1 || self->listen_fd > -1) {
if (pthread_create(&self->talk_thread, NULL, talk_loop, self) != 0) return PyErr_SetFromErrno(PyExc_OSError);
}
int ret = pthread_create(&self->io_thread, NULL, io_loop, self);

View File

@ -84,6 +84,15 @@ with the same |_ --instance-group| will result in new windows being created
in the first |_ {appname}| instance within that group
--listen-on
Tell kitty to listen on the specified UNIX socket or TCP port for control
messages. For example, --listen-on=unix:/tmp/mykitty or
--listen-on=tcp:localhost:12345. On Linux systems, you can also use abstract
UNIX sockets, not associated with a file, like this: --listen-on=unix:@mykitty.
Note that this option will be ignored, unless you set allow_remote_control to yes
in kitty.conf
# Debugging options
--version -v