{"__v":30,"_id":"54fa1d65961fea210092064f","category":{"__v":5,"_id":"54fa1d3fe7a0ba2f00306309","pages":["54fa1d54e7a0ba2f0030630c","54fa1d5de7a0ba2f0030630e","54fa1d65961fea210092064f","54fa1dcff63cf9210041c4c0","551f404b6886f8230055f02f"],"project":"54d53c7b23010a0d001aca0c","version":"54d5635532d98b0d00384afb","sync":{"url":"","isSync":false},"reference":false,"createdAt":"2015-03-06T21:33:51.375Z","from_sync":false,"order":6,"slug":"runners-debuggers","title":"Runners & Debuggers"},"parentDoc":null,"project":"54d53c7b23010a0d001aca0c","user":"54cfa8e1a8a4fd0d00b7fd1d","version":{"__v":10,"_id":"54d5635532d98b0d00384afb","forked_from":"54d53c7c23010a0d001aca0f","project":"54d53c7b23010a0d001aca0c","createdAt":"2015-02-07T00:59:01.934Z","releaseDate":"2015-02-07T00:59:01.934Z","categories":["54d5635632d98b0d00384afc","54d5635632d98b0d00384afd","54d5635632d98b0d00384afe","54d5635632d98b0d00384aff","54d5635632d98b0d00384b00","54d5635632d98b0d00384b01","54d5635632d98b0d00384b02","54d652097e05890d006f153e","54dd1315ca1e5219007e9daa","54e21e2b22de1c230094b147","54e68e62a43fe13500db3879","54fa1d3fe7a0ba2f00306309","551c453a23a1ee190034d19a","551df586e52a0b23000c62b6","551f39be6886f8230055f02a","55a6720751457325000e4d97"],"is_deprecated":false,"is_hidden":false,"is_beta":true,"is_stable":true,"codename":"","version_clean":"0.1.0","version":"0.1"},"updates":["54ff61b4422a14190073fba3"],"next":{"pages":[],"description":""},"createdAt":"2015-03-06T21:34:29.368Z","link_external":false,"link_url":"","githubsync":"","sync_unique":"","hidden":false,"api":{"results":{"codes":[]},"auth":"required","params":[],"url":""},"isReference":false,"order":5,"body":"The debugger proxy (green block below) sits between the running process and the [debugger implementation](doc:debugger-plugin). It is responsible for connecting to the running process either directly, through a debug server or in another way. The [debug socket](doc:debugger-socket) starts the proxy and manages the connection to the [debugger implementation](doc:debugger-plugin). The proxy process is a long-running process that can survive a user session and accepts connections from the [debug socket](doc:debugger-socket).\n\nThe debugger implementation determines the code that is run as the proxy process via the [getProxySource() function](http://cloud9-sdk.readme.io/v0.1/docs/debugger-plugin#getproxysource). You can either use the default proxy as the example in the linked article shows, or you can implement your own proxy as done by the [GDB debugger implementation](https://github.com/c9/c9.ide.run.debug/blob/master/debuggers/gdb/netproxy.js).\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/R4Emsf74SM2MpsMHjiQE_debugger%20architecture%20(1).png\",\n        \"debugger architecture (1).png\",\n        \"818\",\n        \"256\",\n        \"#7c6454\",\n        \"\"\n      ]\n    }\n  ]\n}\n[/block]\n# Function of the Proxy\n\nThe debugger proxy has three primary functions as outlined below. Beyond these functions you are free to add any logic that helps increase the performance by performing logic closer to the debugger rather than on a client.\n\nThe simplest example is the default proxy that is available via `debug.proxySource`. You can check out the source code [here](https://github.com/c9/c9.ide.run.debug/blob/master/debuggers/netproxy.js).\n\n## Listening for Cloud9 Clients\n\nThe proxy *must* accept connections from multiple clients on a port that is equal to the `debugport` of the runner + 1. The simplest way is to create a TCP server that listens to that port and then forward any data in both directions to the debugger. The proxy *should* stay around even after all clients have disconnected.\n[block:callout]\n{\n  \"type\": \"danger\",\n  \"body\": \"The default proxy that is used currently doesn't support multiple clients. This will be updated in the near future. If you are creating your own proxy we advise you to take this into account and allow multiple Cloud9 clients to connect.\"\n}\n[/block]\n## Connecting to the Debugger\n\nThe second responsibility is to connect to the debugger. This is particular to the debugger and is completely up to your implementation. \n\nHere's a table describing how three different implementations handle this.\n[block:html]\n{\n  \"html\": \"<table>\\n  <tr><th>Debugger</th><th>Way the Proxy connects</th></tr>\\n  <tr><td>v8</td><td>Tries to connect the <code>debugport</code> of the runner with an interval of 300ms for each try and it tries 100 times.</td></tr>\\n  <tr><td>gdb</td><td>Starts the GDB Server and interacts with it over stdin/stdout.</td></tr>\\n  <tr><td>xdebug</td><td>Starts a listening TCP server on the <code>debugport</code> of the runner and waits until xdebug connects.</td></tr>\\n</table>\"\n}\n[/block]\n## Sending the Ready-State to the Debug Socket\n\nOnce the proxy connects to the debugger *and* it has created a TCP server to accept client connections, the proxy should notify the socket that it can start listening.\n\nTo do this send the character `ß` as the only output on `stdout`. This will trigger the debug socket to connect.\n\n# Debugger Proxy Life Cycle\n\nIt is up to you to decide how to manage the life cycle of the socket and the proxy process. These are the most common strategies:\n\n## One proxy per debugger session\n\nThis is the strategy chosen by the `v8` debugger. Each time the running process is stopped the debugger proxy will terminate itself. This means that the next time a debugger socket is created it automatically starts a new debugger proxy.\n\nThere is some overhead related to attaching the debugger this way, mostly related to the latency of the connection: \n\n```\n1 roundtrip for the net.connect() that fails\n1 roundtrip + bandwidth for the node process to start\nthe time it takes for the node process to start\nhalf of a roundtrip for the start signal\n1 roundtrip for the net.connect() that succeeds\n```\n\nThis can be < 100ms for connections with latency of 30ms or less. When latency is between 100 - 200ms this can quickly add up to over half a second.\n\n## One proxy for multiple debugger session\n\nThis is the strategy chosen by the `xdebug` debugger. The debugger proxy stays around after it is started and keeps listening for a new xdebug process. This means the initial connection time is similar to the one described above and subsequent connection times only take the time of 1 roundtrip.\n\nThe main difficulty with this strategy is determining when to kill the proxy. This could be done after a long timeout or never. This choice is up to you.","excerpt":"","slug":"debugger-proxy","type":"basic","title":"Debugger Proxy"}
The debugger proxy (green block below) sits between the running process and the [debugger implementation](doc:debugger-plugin). It is responsible for connecting to the running process either directly, through a debug server or in another way. The [debug socket](doc:debugger-socket) starts the proxy and manages the connection to the [debugger implementation](doc:debugger-plugin). The proxy process is a long-running process that can survive a user session and accepts connections from the [debug socket](doc:debugger-socket). The debugger implementation determines the code that is run as the proxy process via the [getProxySource() function](http://cloud9-sdk.readme.io/v0.1/docs/debugger-plugin#getproxysource). You can either use the default proxy as the example in the linked article shows, or you can implement your own proxy as done by the [GDB debugger implementation](https://github.com/c9/c9.ide.run.debug/blob/master/debuggers/gdb/netproxy.js). [block:image] { "images": [ { "image": [ "https://files.readme.io/R4Emsf74SM2MpsMHjiQE_debugger%20architecture%20(1).png", "debugger architecture (1).png", "818", "256", "#7c6454", "" ] } ] } [/block] # Function of the Proxy The debugger proxy has three primary functions as outlined below. Beyond these functions you are free to add any logic that helps increase the performance by performing logic closer to the debugger rather than on a client. The simplest example is the default proxy that is available via `debug.proxySource`. You can check out the source code [here](https://github.com/c9/c9.ide.run.debug/blob/master/debuggers/netproxy.js). ## Listening for Cloud9 Clients The proxy *must* accept connections from multiple clients on a port that is equal to the `debugport` of the runner + 1. The simplest way is to create a TCP server that listens to that port and then forward any data in both directions to the debugger. The proxy *should* stay around even after all clients have disconnected. [block:callout] { "type": "danger", "body": "The default proxy that is used currently doesn't support multiple clients. This will be updated in the near future. If you are creating your own proxy we advise you to take this into account and allow multiple Cloud9 clients to connect." } [/block] ## Connecting to the Debugger The second responsibility is to connect to the debugger. This is particular to the debugger and is completely up to your implementation. Here's a table describing how three different implementations handle this. [block:html] { "html": "<table>\n <tr><th>Debugger</th><th>Way the Proxy connects</th></tr>\n <tr><td>v8</td><td>Tries to connect the <code>debugport</code> of the runner with an interval of 300ms for each try and it tries 100 times.</td></tr>\n <tr><td>gdb</td><td>Starts the GDB Server and interacts with it over stdin/stdout.</td></tr>\n <tr><td>xdebug</td><td>Starts a listening TCP server on the <code>debugport</code> of the runner and waits until xdebug connects.</td></tr>\n</table>" } [/block] ## Sending the Ready-State to the Debug Socket Once the proxy connects to the debugger *and* it has created a TCP server to accept client connections, the proxy should notify the socket that it can start listening. To do this send the character `ß` as the only output on `stdout`. This will trigger the debug socket to connect. # Debugger Proxy Life Cycle It is up to you to decide how to manage the life cycle of the socket and the proxy process. These are the most common strategies: ## One proxy per debugger session This is the strategy chosen by the `v8` debugger. Each time the running process is stopped the debugger proxy will terminate itself. This means that the next time a debugger socket is created it automatically starts a new debugger proxy. There is some overhead related to attaching the debugger this way, mostly related to the latency of the connection: ``` 1 roundtrip for the net.connect() that fails 1 roundtrip + bandwidth for the node process to start the time it takes for the node process to start half of a roundtrip for the start signal 1 roundtrip for the net.connect() that succeeds ``` This can be < 100ms for connections with latency of 30ms or less. When latency is between 100 - 200ms this can quickly add up to over half a second. ## One proxy for multiple debugger session This is the strategy chosen by the `xdebug` debugger. The debugger proxy stays around after it is started and keeps listening for a new xdebug process. This means the initial connection time is similar to the one described above and subsequent connection times only take the time of 1 roundtrip. The main difficulty with this strategy is determining when to kill the proxy. This could be done after a long timeout or never. This choice is up to you.