[Lldb-commits] [PATCH] D59104: [lldb-vscode] Make server mode work on Windows

2019-03-07 Thread Zachary Turner via Phabricator via lldb-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL355637: [lldb-vscode] Support running in server mode on 
Windows. (authored by zturner, committed by ).
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D59104?vs=189759&id=189777#toc

Repository:
  rL LLVM

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D59104/new/

https://reviews.llvm.org/D59104

Files:
  lldb/trunk/tools/lldb-vscode/CMakeLists.txt
  lldb/trunk/tools/lldb-vscode/IOStream.cpp
  lldb/trunk/tools/lldb-vscode/IOStream.h
  lldb/trunk/tools/lldb-vscode/VSCode.cpp
  lldb/trunk/tools/lldb-vscode/VSCode.h
  lldb/trunk/tools/lldb-vscode/lldb-vscode.cpp
  lldb/trunk/tools/lldb-vscode/package.json

Index: lldb/trunk/tools/lldb-vscode/lldb-vscode.cpp
===
--- lldb/trunk/tools/lldb-vscode/lldb-vscode.cpp
+++ lldb/trunk/tools/lldb-vscode/lldb-vscode.cpp
@@ -23,6 +23,7 @@
 #define NOMINMAX
 #include 
 #undef GetObject
+#include 
 #else
 #include 
 #include 
@@ -53,7 +54,6 @@
 constexpr const char *dev_null_path = "nul";
 
 #else
-typedef int SOCKET;
 constexpr const char *dev_null_path = "/dev/null";
 
 #endif
@@ -68,9 +68,9 @@
 
 enum VSCodeBroadcasterBits { eBroadcastBitStopEventThread = 1u << 0 };
 
-int AcceptConnection(int portno) {
+SOCKET AcceptConnection(int portno) {
   // Accept a socket connection from any host on "portno".
-  int newsockfd = -1;
+  SOCKET newsockfd = -1;
   struct sockaddr_in serv_addr, cli_addr;
   SOCKET sockfd = socket(AF_INET, SOCK_STREAM, 0);
   if (sockfd < 0) {
@@ -2635,23 +2635,19 @@
 #endif
   int portno = atoi(arg);
   printf("Listening on port %i...\n", portno);
-  int socket_fd = AcceptConnection(portno);
+  SOCKET socket_fd = AcceptConnection(portno);
   if (socket_fd >= 0) {
-// We must open two FILE objects, one for reading and one for writing
-// the FILE objects have a mutex in them that won't allow reading and
-// writing to the socket stream.
-g_vsc.in = fdopen(socket_fd, "r");
-g_vsc.out = fdopen(socket_fd, "w");
-if (g_vsc.in == nullptr || g_vsc.out == nullptr) {
-  if (g_vsc.log)
-*g_vsc.log << "fdopen failed (" << strerror(errno) << ")"
-   << std::endl;
-  exit(1);
-}
+g_vsc.input.descriptor = StreamDescriptor::from_socket(socket_fd, true);
+g_vsc.output.descriptor =
+StreamDescriptor::from_socket(socket_fd, false);
   } else {
 exit(1);
   }
 }
+  } else {
+g_vsc.input.descriptor = StreamDescriptor::from_file(fileno(stdin), false);
+g_vsc.output.descriptor =
+StreamDescriptor::from_file(fileno(stdout), false);
   }
   auto request_handlers = GetRequestHandlers();
   uint32_t packet_idx = 0;
Index: lldb/trunk/tools/lldb-vscode/CMakeLists.txt
===
--- lldb/trunk/tools/lldb-vscode/CMakeLists.txt
+++ lldb/trunk/tools/lldb-vscode/CMakeLists.txt
@@ -15,6 +15,7 @@
   BreakpointBase.cpp
   ExceptionBreakpoint.cpp
   FunctionBreakpoint.cpp
+  IOStream.cpp
   JSONUtils.cpp
   LLDBUtils.cpp
   SourceBreakpoint.cpp
Index: lldb/trunk/tools/lldb-vscode/IOStream.h
===
--- lldb/trunk/tools/lldb-vscode/IOStream.h
+++ lldb/trunk/tools/lldb-vscode/IOStream.h
@@ -0,0 +1,69 @@
+//===-- IOStream.h --*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#ifndef LLDBVSCODE_IOSTREAM_H_
+#define LLDBVSCODE_IOSTREAM_H_
+
+#if defined(_WIN32)
+// We need to #define NOMINMAX in order to skip `min()` and `max()` macro
+// definitions that conflict with other system headers.
+// We also need to #undef GetObject (which is defined to GetObjectW) because
+// the JSON code we use also has methods named `GetObject()` and we conflict
+// against these.
+#define NOMINMAX
+#include 
+#else
+typedef int SOCKET;
+#endif
+
+#include "llvm/ADT/StringRef.h"
+
+#include 
+#include 
+
+// Windows requires different system calls for dealing with sockets and other
+// types of files, so we can't simply have one code path that just uses read
+// and write everywhere.  So we need an abstraction in order to allow us to
+// treat them identically.
+namespace lldb_vscode {
+struct StreamDescriptor {
+  StreamDescriptor();
+  ~StreamDescriptor();
+  StreamDescriptor(StreamDescriptor &&other);
+
+  StreamDescriptor &operator=(StreamDescriptor &&other);
+
+  static StreamDescriptor from_socket(SOCKET s, bool close);
+  static StreamDescriptor from_file(int fd, bool 

[Lldb-commits] [PATCH] D59104: [lldb-vscode] Make server mode work on Windows

2019-03-07 Thread Zachary Turner via Phabricator via lldb-commits
zturner created this revision.
zturner added a reviewer: clayborg.
Herald added a subscriber: mgorny.

For historical reasons, Windows unfortunately doesn't support using sockets in 
standard system calls like read/write, which means that they also can't be 
buffered with a `FILE*`.  This violates some fundamental assumptions of how 
lldb-vscode was written, so fixing it requires some replumbing of the guts.  I 
introduced an abstraction called `IOStream` which basically knows whether the 
descriptor is a socket or a non-socket, and then delegates to the appropriate 
underlying APIs accordingly.  This means calling `read/write` on `stdin/stdout` 
and calling `recv/send` on sockets.  Luckily this same strategy will also work 
on non-Windows platforms, so the abstractions needed aren't too egregious.


https://reviews.llvm.org/D59104

Files:
  lldb/tools/lldb-vscode/CMakeLists.txt
  lldb/tools/lldb-vscode/IOStream.cpp
  lldb/tools/lldb-vscode/IOStream.h
  lldb/tools/lldb-vscode/VSCode.cpp
  lldb/tools/lldb-vscode/VSCode.h
  lldb/tools/lldb-vscode/lldb-vscode.cpp
  lldb/tools/lldb-vscode/package.json

Index: lldb/tools/lldb-vscode/package.json
===
--- lldb/tools/lldb-vscode/package.json
+++ lldb/tools/lldb-vscode/package.json
@@ -56,6 +56,9 @@
 	]
 },
 "program": "./bin/lldb-vscode",
+"windows": {
+	"program": "./bin/lldb-vscode.exe"
+},
 "configurationAttributes": {
 	"launch": {
 		"required": [
Index: lldb/tools/lldb-vscode/lldb-vscode.cpp
===
--- lldb/tools/lldb-vscode/lldb-vscode.cpp
+++ lldb/tools/lldb-vscode/lldb-vscode.cpp
@@ -23,6 +23,7 @@
 #define NOMINMAX
 #include 
 #undef GetObject
+#include 
 #else
 #include 
 #include 
@@ -68,9 +69,9 @@
 
 enum VSCodeBroadcasterBits { eBroadcastBitStopEventThread = 1u << 0 };
 
-int AcceptConnection(int portno) {
+SOCKET AcceptConnection(int portno) {
   // Accept a socket connection from any host on "portno".
-  int newsockfd = -1;
+  SOCKET newsockfd = -1;
   struct sockaddr_in serv_addr, cli_addr;
   SOCKET sockfd = socket(AF_INET, SOCK_STREAM, 0);
   if (sockfd < 0) {
@@ -2635,23 +2636,19 @@
 #endif
   int portno = atoi(arg);
   printf("Listening on port %i...\n", portno);
-  int socket_fd = AcceptConnection(portno);
+  SOCKET socket_fd = AcceptConnection(portno);
   if (socket_fd >= 0) {
-// We must open two FILE objects, one for reading and one for writing
-// the FILE objects have a mutex in them that won't allow reading and
-// writing to the socket stream.
-g_vsc.in = fdopen(socket_fd, "r");
-g_vsc.out = fdopen(socket_fd, "w");
-if (g_vsc.in == nullptr || g_vsc.out == nullptr) {
-  if (g_vsc.log)
-*g_vsc.log << "fdopen failed (" << strerror(errno) << ")"
-   << std::endl;
-  exit(1);
-}
+g_vsc.input.descriptor = StreamDescriptor::from_socket(socket_fd, true);
+g_vsc.output.descriptor =
+StreamDescriptor::from_socket(socket_fd, false);
   } else {
 exit(1);
   }
 }
+  } else {
+g_vsc.input.descriptor = StreamDescriptor::from_file(fileno(stdin), false);
+g_vsc.output.descriptor =
+StreamDescriptor::from_file(fileno(stdout), false);
   }
   auto request_handlers = GetRequestHandlers();
   uint32_t packet_idx = 0;
Index: lldb/tools/lldb-vscode/VSCode.h
===
--- lldb/tools/lldb-vscode/VSCode.h
+++ lldb/tools/lldb-vscode/VSCode.h
@@ -19,6 +19,7 @@
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
+#include "llvm/Support/raw_ostream.h"
 
 #include "lldb/API/SBAttachInfo.h"
 #include "lldb/API/SBBreakpoint.h"
@@ -43,6 +44,7 @@
 
 #include "ExceptionBreakpoint.h"
 #include "FunctionBreakpoint.h"
+#include "IOStream.h"
 #include "SourceBreakpoint.h"
 #include "SourceReference.h"
 
@@ -62,8 +64,8 @@
 enum class OutputType { Console, Stdout, Stderr, Telemetry };
 
 struct VSCode {
-  FILE *in;
-  FILE *out;
+  InputStream input;
+  OutputStream output;
   lldb::SBDebugger debugger;
   lldb::SBTarget target;
   lldb::SBAttachInfo attach_info;
@@ -94,8 +96,6 @@
   ~VSCode();
   VSCode(const VSCode &rhs) = delete;
   void operator=(const VSCode &rhs) = delete;
-  void CloseInputStream();
-  void CloseOutputStream();
   int64_t GetLineForPC(int64_t sourceReference, lldb::addr_t pc) const;
   ExceptionBreakpoint *GetExceptionBreakpoint(const std::string &filter);
   ExceptionBreakpoint *GetExceptionBreakpoint(const lldb::break_id_t bp_id);
Index: lldb/tools/lldb-vscode/VSCode.cpp
===
--- lldb/tools/lldb-vscode/VSCode.cpp
+++ lldb/tools/lldb-vscode/VSCode.cpp
@@ -10,12 +10,15 @@
 #include 
 #include 
 
-#include "VSCode.h"
 #include "LLDBUtils.h"
+#incl