Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support communication with the debugged process over UNIX-domain sockets #190

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions doc/Vdebug.txt
Original file line number Diff line number Diff line change
Expand Up @@ -785,8 +785,10 @@ retain option settings by adding them to your vimrc.

The default options look like this: >
let g:vdebug_options= {
\ "socket_type": "tcp",
\ "port" : 9000,
\ "server" : 'localhost',
\ "unix_permissions": 0700,
\ "timeout" : 20,
\ "on_close" : 'detach',
\ "break_on_open" : 1,
Expand All @@ -810,6 +812,13 @@ if you don't set them.

Here is a list of all the available options.

*VdebugOptions-socket_type*
g:vdebug_options["socket_type"] (default = "tcp")
This sets whether Vdebug waits over a TCP or an Unix-domain
socket. When set to "tcp" the listening address is configured via
the port and server options, when set to "unix" the listening path
is configured via the unix_path option.

*VdebugOptions-port*
g:vdebug_options["port"] (default = 9000)
This sets the port that Vdebug will use to listen for connections. Xdebug
Expand All @@ -823,6 +832,16 @@ g:vdebug_options["server"] (default = "localhost")
running on the same machine and also connecting to localhost. If you want
to debug a script on a different machine, look at |VdebugRemote|.

*VdebugOptions-unix_path*
g:vdebug_options["unix_path"] (default = empty)
This sets the path that Vdebug will use to listen for connections
when listening over an Unix-domain socket.

*VdebugOptions-unix_permissions*
g:vdebug_options["unix_permissions"] (default = 0700)
This sets the permissions of the Unix-domain socket that Vdebug
will use to listen for connections.

*VdebugOptions-timeout*
g:vdebug_options["timeout"] (default = 20)
Number of seconds to wait for when listening for a connection. VIM will
Expand Down
54 changes: 46 additions & 8 deletions plugin/python/vdebug/dbgp.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import vdebug.log
import base64
import time
import os

""" Response objects for the DBGP module."""

Expand Down Expand Up @@ -381,20 +382,31 @@ class Connection:
address = None
isconned = 0

def __init__(self, host = '', port = 9000, timeout = 30, input_stream = None):
def __init__(self, endpoint, timeout = 30, input_stream = None):
"""Create a new Connection.

The connection is not established until open() is called.

host -- host name where debugger is running (default '')
port -- port number which debugger is listening on (default 9000)
endpoint -- dictionary containing connection parameters
{
"socket_type": "tcp" (default)/"unix",
# for TCP sockets
"server": "localhost",
"port": 9000,
# for UNIX-domain sockets
"unix_path": "/path/to/socket",
"unix_permissions": 0777,
}
timeout -- time in seconds to wait for a debugger connection before giving up (default 30)
input_stream -- object for checking input stream and user interrupts (default None)

Both "server" and "port" parameters are required for TCP sockets, for UNIX-domain sockets
only "unix_path" is required.
"""
self.port = port
self.host = host
self.endpoint = endpoint
self.timeout = timeout
self.input_stream = input_stream
self.address_type = self.endpoint['socket_type']

def __del__(self):
"""Make sure the connection is closed."""
Expand All @@ -404,15 +416,41 @@ def isconnected(self):
"""Whether the connection has been established."""
return self.isconned

def address_description(self):
"""Human-readable local address"""
if self.endpoint['socket_type'] == 'tcp':
return "%s:%s" %(self.endpoint['server'],self.endpoint['port'])
else:
return self.endpoint['unix_path']

def peer_description(self):
"""Human-readable peer address"""
if self.endpoint['socket_type'] == 'tcp':
return "%s:%s" %(self.address[0],self.address[1])
else:
return self.endpoint['unix_path']

def open(self):
"""Listen for a connection from the debugger. Listening for the actual
connection is handled by self.listen()."""
print 'Waiting for a connection (Ctrl-C to cancel, this message will self-destruct in ',self.timeout,' seconds...)'
serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
if self.address_type == 'tcp':
serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
else:
serv = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
try:
serv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
serv.setblocking(0)
serv.bind((self.host, self.port))
if self.endpoint.get('socket_type', 'tcp') == 'tcp':
serv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
serv.bind((self.endpoint['server'], self.endpoint['port']))
else:
path = self.endpoint['unix_path']
if os.path.exists(path):
os.unlink(path)
serv.bind(path)
if self.endpoint.get('unix_permissions'):
os.chmod(path, self.endpoint['unix_permissions']);

serv.listen(5)
(self.sock, self.address) = self.listen(serv, self.timeout)
self.sock.settimeout(None)
Expand Down
30 changes: 20 additions & 10 deletions plugin/python/vdebug/runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,14 @@ class Runner:
an interface that Vim can use to send commands.
"""

ENDPOINT_ARGS = [
('socket_type', str),
('server', str),
('port', int),
('unix_path', str),
('unix_group', str),
('unix_permissions', int),
]
def __init__(self):
self.api = None
vdebug.opts.Options.set(vim.eval('g:vdebug_options'))
Expand All @@ -39,21 +47,23 @@ def open(self):
vdebug.log.Log.set_logger(vdebug.log.FileLogger(\
vdebug.opts.Options.get('debug_file_level'),\
vdebug.opts.Options.get('debug_file')))
endpoint = {}
for arg, pytype in Runner.ENDPOINT_ARGS:
if vdebug.opts.Options.isset(arg):
endpoint[arg] = vdebug.opts.Options.get(arg, pytype)
self.listen(\
vdebug.opts.Options.get('server'),\
vdebug.opts.Options.get('port',int),\
endpoint,\
vdebug.opts.Options.get('timeout',int))

self.ui.open()
self.keymapper.map()
self.ui.set_listener_details(\
vdebug.opts.Options.get('server'),\
vdebug.opts.Options.get('port'),\
self.api.conn.address_description(),\
vdebug.opts.Options.get('ide_key'))

addr = self.api.conn.address
vdebug.log.Log("Found connection from " + str(addr),vdebug.log.Logger.INFO)
self.ui.set_conn_details(addr[0],addr[1])
addr = self.api.conn.peer_description()
vdebug.log.Log("Found connection from " + addr,vdebug.log.Logger.INFO)
self.ui.set_conn_details(addr)

self.set_features()
self.breakpoints.update_lines(self.ui.get_breakpoint_sign_positions())
Expand Down Expand Up @@ -253,7 +263,7 @@ def run_to_cursor(self):
self.api.breakpoint_set(bp.get_cmd())
self.run()

def listen(self,server,port,timeout):
def listen(self,endpoint,timeout):
"""Open the vdebug.dbgp API with connection.

Uses existing connection if possible.
Expand All @@ -269,8 +279,8 @@ def listen(self,server,port,timeout):
check_ide_key = True
if len(ide_key) == 0:
check_ide_key = False
connection = vdebug.dbgp.Connection(server,port,\

connection = vdebug.dbgp.Connection(endpoint,
timeout,vdebug.util.InputStream())

self.api = vdebug.dbgp.Api(connection)
Expand Down
8 changes: 4 additions & 4 deletions plugin/python/vdebug/ui/vimui.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,14 +87,14 @@ def mark_as_stopped(self):
self.statuswin.set_status("stopped")
self.remove_conn_details()

def set_conn_details(self,addr,port):
self.statuswin.insert("Connected to %s:%s" %(addr,port),2,True)
def set_conn_details(self,description):
self.statuswin.insert("Connected to %s" %(description),2,True)

def remove_conn_details(self):
self.statuswin.insert("Not connected",2,True)

def set_listener_details(self,addr,port,idekey):
details = "Listening on %s:%s" %(addr,port)
def set_listener_details(self,description,idekey):
details = "Listening on %s" %(description)
if len(idekey):
details += " (IDE key: %s)" % idekey
self.statuswin.insert(details,1,True)
Expand Down
2 changes: 2 additions & 0 deletions plugin/vdebug.vim
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,11 @@ let g:vdebug_keymap_defaults = {
\}

let g:vdebug_options_defaults = {
\ "socket_type": "tcp",
\ "port" : 9000,
\ "timeout" : 20,
\ "server" : 'localhost',
\ "unix_permissions": 0700,
\ "on_close" : 'detach',
\ "break_on_open" : 1,
\ "ide_key" : '',
Expand Down