| OLD | NEW |
| 1 // Copyright (c) 2015, the Dartino project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, the Dartino project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE.md file. | 3 // BSD-style license that can be found in the LICENSE.md file. |
| 4 | 4 |
| 5 #include <arpa/inet.h> | 5 #include <arpa/inet.h> |
| 6 #include <libgen.h> | 6 #include <libgen.h> |
| 7 #include <limits.h> | 7 #include <limits.h> |
| 8 #include <math.h> | 8 #include <math.h> |
| 9 #include <pwd.h> | 9 #include <pwd.h> |
| 10 #include <stdarg.h> | 10 #include <stdarg.h> |
| (...skipping 13 matching lines...) Expand all Loading... |
| 24 #include "src/shared/globals.h" | 24 #include "src/shared/globals.h" |
| 25 #include "src/shared/native_socket.h" | 25 #include "src/shared/native_socket.h" |
| 26 #include "src/shared/platform.h" | 26 #include "src/shared/platform.h" |
| 27 #include "src/shared/utils.h" | 27 #include "src/shared/utils.h" |
| 28 #include "src/shared/version.h" | 28 #include "src/shared/version.h" |
| 29 #include "src/tools/driver/connection.h" | 29 #include "src/tools/driver/connection.h" |
| 30 #include "src/tools/driver/platform.h" | 30 #include "src/tools/driver/platform.h" |
| 31 | 31 |
| 32 // Fast front-end for persistent compiler process. | 32 // Fast front-end for persistent compiler process. |
| 33 // | 33 // |
| 34 // To obtain the required performance of command line tools, the fletch | 34 // To obtain the required performance of command line tools, the dartino |
| 35 // compiler based on dart2js needs to stay persistent in memory. The start-up | 35 // compiler based on dart2js needs to stay persistent in memory. The start-up |
| 36 // time of the Dart VM, and its performance of unoptimized code make this | 36 // time of the Dart VM, and its performance of unoptimized code make this |
| 37 // necessary. | 37 // necessary. |
| 38 // | 38 // |
| 39 // An alternative would be to have a small Dart program connect to the VM, but | 39 // An alternative would be to have a small Dart program connect to the VM, but |
| 40 // measurements show this C++ program to be 10-20 times faster than a | 40 // measurements show this C++ program to be 10-20 times faster than a |
| 41 // hello-world program in Dart. | 41 // hello-world program in Dart. |
| 42 // | 42 // |
| 43 // If the persistent process isn't running, it will be started by this program. | 43 // If the persistent process isn't running, it will be started by this program. |
| 44 // | 44 // |
| 45 // Consequently, this process always communicates with a server process that | 45 // Consequently, this process always communicates with a server process that |
| 46 // isn't considered a child of itself. | 46 // isn't considered a child of itself. |
| 47 // | 47 // |
| 48 // Details about starting the server: to avoid starting multiple servers, this | 48 // Details about starting the server: to avoid starting multiple servers, this |
| 49 // program attempts obtain an exclusive lock during the initial handshake with | 49 // program attempts obtain an exclusive lock during the initial handshake with |
| 50 // the server. If the server doesn't respond, it is started, and the lock isn't | 50 // the server. If the server doesn't respond, it is started, and the lock isn't |
| 51 // released until the server is ready. | 51 // released until the server is ready. |
| 52 | 52 |
| 53 namespace fletch { | 53 namespace dartino { |
| 54 | 54 |
| 55 static const int COMPILER_CRASHED = 253; | 55 static const int COMPILER_CRASHED = 253; |
| 56 | 56 |
| 57 static char* program_name = NULL; | 57 static char* program_name = NULL; |
| 58 | 58 |
| 59 // The file where this program looks for the TCP/IP port for talking | 59 // The file where this program looks for the TCP/IP port for talking |
| 60 // to the persistent process. Controlled by user by setting | 60 // to the persistent process. Controlled by user by setting |
| 61 // environment variable FLETCH_PORT_FILE. | 61 // environment variable DARTINO_PORT_FILE. |
| 62 static char fletch_config_file[MAXPATHLEN]; | 62 static char dartino_config_file[MAXPATHLEN]; |
| 63 | 63 |
| 64 // The port that was read from [fletch_config_file]. | 64 // The port that was read from [dartino_config_file]. |
| 65 static int fletch_socket_port; | 65 static int dartino_socket_port; |
| 66 | 66 |
| 67 static const char fletch_config_name[] = ".fletch"; | 67 static const char dartino_config_name[] = ".dartino"; |
| 68 | 68 |
| 69 static const char fletch_config_env_name[] = "FLETCH_PORT_FILE"; | 69 static const char dartino_config_env_name[] = "DARTINO_PORT_FILE"; |
| 70 | 70 |
| 71 static const char* fletch_config_location = NULL; | 71 static const char* dartino_config_location = NULL; |
| 72 | 72 |
| 73 static int fletch_config_fd; | 73 static int dartino_config_fd; |
| 74 | 74 |
| 75 static const char dart_vm_env_name[] = "DART_VM"; | 75 static const char dart_vm_env_name[] = "DART_VM"; |
| 76 | 76 |
| 77 static int exit_code = COMPILER_CRASHED; | 77 static int exit_code = COMPILER_CRASHED; |
| 78 | 78 |
| 79 static void WriteFully(int fd, uint8* data, ssize_t length); | 79 static void WriteFully(int fd, uint8* data, ssize_t length); |
| 80 | 80 |
| 81 void Die(const char* format, ...) { | 81 void Die(const char* format, ...) { |
| 82 va_list args; | 82 va_list args; |
| 83 va_start(args, format); | 83 va_start(args, format); |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 142 } | 142 } |
| 143 | 143 |
| 144 bool FileExists(const char* name) { | 144 bool FileExists(const char* name) { |
| 145 struct stat info; | 145 struct stat info; |
| 146 if (stat(name, &info) == 0) { | 146 if (stat(name, &info) == 0) { |
| 147 return (info.st_mode & S_IFREG) != 0; | 147 return (info.st_mode & S_IFREG) != 0; |
| 148 } | 148 } |
| 149 return false; | 149 return false; |
| 150 } | 150 } |
| 151 | 151 |
| 152 void FletchConfigFile(char* result, const char* directory) { | 152 void DartinoConfigFile(char* result, const char* directory) { |
| 153 // TODO(ahe): Use StrCat or StrCpy instead. | 153 // TODO(ahe): Use StrCat or StrCpy instead. |
| 154 char* ptr = stpncpy(result, directory, MAXPATHLEN); | 154 char* ptr = stpncpy(result, directory, MAXPATHLEN); |
| 155 if (ptr[-1] != '/') { | 155 if (ptr[-1] != '/') { |
| 156 ptr[0] = '/'; | 156 ptr[0] = '/'; |
| 157 ptr++; | 157 ptr++; |
| 158 } | 158 } |
| 159 // TODO(ahe): Use StrCat or StrCpy instead. | 159 // TODO(ahe): Use StrCat or StrCpy instead. |
| 160 strncpy(ptr, fletch_config_name, sizeof(fletch_config_name)); | 160 strncpy(ptr, dartino_config_name, sizeof(dartino_config_name)); |
| 161 } | 161 } |
| 162 | 162 |
| 163 void ParentDir(char* directory) { | 163 void ParentDir(char* directory) { |
| 164 char copy[MAXPATHLEN + 1]; | 164 char copy[MAXPATHLEN + 1]; |
| 165 // On Linux, dirname's argument may be modified. On Mac OS X, it returns a | 165 // On Linux, dirname's argument may be modified. On Mac OS X, it returns a |
| 166 // pointer to internal memory. Probably not thread safe. So we first copy | 166 // pointer to internal memory. Probably not thread safe. So we first copy |
| 167 // directory to a place we don't mind getting modified. | 167 // directory to a place we don't mind getting modified. |
| 168 // TODO(ahe): Use StrCat or StrCpy instead. | 168 // TODO(ahe): Use StrCat or StrCpy instead. |
| 169 strncpy(copy, directory, MAXPATHLEN); | 169 strncpy(copy, directory, MAXPATHLEN); |
| 170 char* parent = dirname(copy); | 170 char* parent = dirname(copy); |
| 171 if (parent == NULL) { | 171 if (parent == NULL) { |
| 172 Die("%s: Unable to compute parent directory of '%s': %s", program_name, | 172 Die("%s: Unable to compute parent directory of '%s': %s", program_name, |
| 173 directory, strerror(errno)); | 173 directory, strerror(errno)); |
| 174 } | 174 } |
| 175 // TODO(ahe): Use StrCat or StrCpy instead. | 175 // TODO(ahe): Use StrCat or StrCpy instead. |
| 176 strncpy(directory, parent, MAXPATHLEN); | 176 strncpy(directory, parent, MAXPATHLEN); |
| 177 } | 177 } |
| 178 | 178 |
| 179 // Detect the configuration and initialize the following variables: | 179 // Detect the configuration and initialize the following variables: |
| 180 // | 180 // |
| 181 // * fletch_config_file | 181 // * dartino_config_file |
| 182 // | 182 // |
| 183 // We first look for an environment variable named FLETCH_PORT_FILE. If | 183 // We first look for an environment variable named DARTINO_PORT_FILE. If |
| 184 // defined, it gives the value of fletch_config_file. | 184 // defined, it gives the value of dartino_config_file. |
| 185 // | 185 // |
| 186 // If FLETCH_PORT_FILE isn't defined, we look for the environment variable | 186 // If DARTINO_PORT_FILE isn't defined, we look for the environment variable |
| 187 // HOME, if defined, the value of fletch_config_file becomes "${HOME}/.fletch". | 187 // HOME, if defined, the value of dartino_config_file becomes |
| 188 // "${HOME}/.dartino". |
| 188 // | 189 // |
| 189 // If HOME isn't defined, we find the user's home directory via getpwuid_r. | 190 // If HOME isn't defined, we find the user's home directory via getpwuid_r. |
| 190 static void DetectConfiguration() { | 191 static void DetectConfiguration() { |
| 191 // First look for the environment variable FLETCH_PORT_FILE. | 192 // First look for the environment variable DARTINO_PORT_FILE. |
| 192 char* fletch_config_env = getenv(fletch_config_env_name); | 193 char* dartino_config_env = getenv(dartino_config_env_name); |
| 193 if (fletch_config_env != NULL) { | 194 if (dartino_config_env != NULL) { |
| 194 fletch_config_location = fletch_config_env_name; | 195 dartino_config_location = dartino_config_env_name; |
| 195 StrCpy(fletch_config_file, sizeof(fletch_config_file), fletch_config_env, | 196 StrCpy(dartino_config_file, sizeof(dartino_config_file), dartino_config_env, |
| 196 strlen(fletch_config_env) + 1); | 197 strlen(dartino_config_env) + 1); |
| 197 return; | 198 return; |
| 198 } | 199 } |
| 199 | 200 |
| 200 // Then look for the environment variable HOME. | 201 // Then look for the environment variable HOME. |
| 201 char* home_env = getenv("HOME"); | 202 char* home_env = getenv("HOME"); |
| 202 if (home_env != NULL) { | 203 if (home_env != NULL) { |
| 203 fletch_config_location = "HOME"; | 204 dartino_config_location = "HOME"; |
| 204 FletchConfigFile(fletch_config_file, home_env); | 205 DartinoConfigFile(dartino_config_file, home_env); |
| 205 return; | 206 return; |
| 206 } | 207 } |
| 207 | 208 |
| 208 // Fall back to getpwuid_r for obtaining the home directory. | 209 // Fall back to getpwuid_r for obtaining the home directory. |
| 209 int pwd_buffer_size = sysconf(_SC_GETPW_R_SIZE_MAX); | 210 int pwd_buffer_size = sysconf(_SC_GETPW_R_SIZE_MAX); |
| 210 if (pwd_buffer_size == -1) { | 211 if (pwd_buffer_size == -1) { |
| 211 // On Linux, we can't guarantee a sensible return value. So let's assume | 212 // On Linux, we can't guarantee a sensible return value. So let's assume |
| 212 // that each char* in struct passwd are less than MAXPATHLEN. There are 5 | 213 // that each char* in struct passwd are less than MAXPATHLEN. There are 5 |
| 213 // of those, and then one extra for null-termination and good measure. | 214 // of those, and then one extra for null-termination and good measure. |
| 214 pwd_buffer_size = MAXPATHLEN * 6; | 215 pwd_buffer_size = MAXPATHLEN * 6; |
| 215 } | 216 } |
| 216 char* pwd_buffer = StrAlloc(pwd_buffer_size); | 217 char* pwd_buffer = StrAlloc(pwd_buffer_size); |
| 217 | 218 |
| 218 struct passwd pwd; | 219 struct passwd pwd; |
| 219 struct passwd* result = NULL; | 220 struct passwd* result = NULL; |
| 220 int error_code = | 221 int error_code = |
| 221 getpwuid_r(getuid(), &pwd, pwd_buffer, pwd_buffer_size, &result); | 222 getpwuid_r(getuid(), &pwd, pwd_buffer, pwd_buffer_size, &result); |
| 222 if (error_code != 0) { | 223 if (error_code != 0) { |
| 223 Die("%s: Unable to determine home directory: %s", program_name, | 224 Die("%s: Unable to determine home directory: %s", program_name, |
| 224 strerror(error_code)); | 225 strerror(error_code)); |
| 225 } | 226 } |
| 226 if (result == NULL) { | 227 if (result == NULL) { |
| 227 Die("%s: Unable to determine home directory: Entry for user not found.", | 228 Die("%s: Unable to determine home directory: Entry for user not found.", |
| 228 program_name); | 229 program_name); |
| 229 } | 230 } |
| 230 fletch_config_location = "/etc/passwd"; | 231 dartino_config_location = "/etc/passwd"; |
| 231 FletchConfigFile(fletch_config_file, pwd.pw_dir); | 232 DartinoConfigFile(dartino_config_file, pwd.pw_dir); |
| 232 free(pwd_buffer); | 233 free(pwd_buffer); |
| 233 } | 234 } |
| 234 | 235 |
| 235 // Opens and locks the config file named by fletch_config_file and initialize | 236 // Opens and locks the config file named by dartino_config_file and initialize |
| 236 // the variable fletch_config_fd. If use_blocking is true, this method will | 237 // the variable dartino_config_fd. If use_blocking is true, this method will |
| 237 // block until the lock is obtained. | 238 // block until the lock is obtained. |
| 238 static void LockConfigFile(bool use_blocking) { | 239 static void LockConfigFile(bool use_blocking) { |
| 239 int fd = TEMP_FAILURE_RETRY( | 240 int fd = TEMP_FAILURE_RETRY( |
| 240 open(fletch_config_file, O_RDONLY | O_CREAT, S_IRUSR | S_IWUSR)); | 241 open(dartino_config_file, O_RDONLY | O_CREAT, S_IRUSR | S_IWUSR)); |
| 241 if (fd == -1) { | 242 if (fd == -1) { |
| 242 Die("%s: Unable to open '%s' failed: %s.\nTry checking the value of '%s'.", | 243 Die("%s: Unable to open '%s' failed: %s.\nTry checking the value of '%s'.", |
| 243 program_name, fletch_config_file, strerror(errno), | 244 program_name, dartino_config_file, strerror(errno), |
| 244 fletch_config_location); | 245 dartino_config_location); |
| 245 } | 246 } |
| 246 | 247 |
| 247 int operation = LOCK_EX; | 248 int operation = LOCK_EX; |
| 248 if (!use_blocking) { | 249 if (!use_blocking) { |
| 249 operation |= LOCK_NB; | 250 operation |= LOCK_NB; |
| 250 } | 251 } |
| 251 if (TEMP_FAILURE_RETRY(flock(fd, operation)) == -1) { | 252 if (TEMP_FAILURE_RETRY(flock(fd, operation)) == -1) { |
| 252 if (use_blocking || errno != EWOULDBLOCK) { | 253 if (use_blocking || errno != EWOULDBLOCK) { |
| 253 Die("%s: flock '%s' failed: %s.", program_name, fletch_config_file, | 254 Die("%s: flock '%s' failed: %s.", program_name, dartino_config_file, |
| 254 strerror(errno)); | 255 strerror(errno)); |
| 255 } | 256 } |
| 256 } | 257 } |
| 257 | 258 |
| 258 fletch_config_fd = fd; | 259 dartino_config_fd = fd; |
| 259 } | 260 } |
| 260 | 261 |
| 261 // Release the lock on fletch_config_fd. | 262 // Release the lock on dartino_config_fd. |
| 262 static void UnlockConfigFile() { | 263 static void UnlockConfigFile() { |
| 263 // Closing the file descriptor will release the lock. | 264 // Closing the file descriptor will release the lock. |
| 264 Close(fletch_config_fd); | 265 Close(dartino_config_fd); |
| 265 } | 266 } |
| 266 | 267 |
| 267 static void ReadDriverConfig() { | 268 static void ReadDriverConfig() { |
| 268 char buffer[80]; | 269 char buffer[80]; |
| 269 size_t offset = 0; | 270 size_t offset = 0; |
| 270 size_t length = sizeof(buffer) - 1; | 271 size_t length = sizeof(buffer) - 1; |
| 271 while (offset < length) { | 272 while (offset < length) { |
| 272 ssize_t bytes = TEMP_FAILURE_RETRY( | 273 ssize_t bytes = TEMP_FAILURE_RETRY( |
| 273 read(fletch_config_fd, buffer + offset, length - offset)); | 274 read(dartino_config_fd, buffer + offset, length - offset)); |
| 274 if (bytes < 0) { | 275 if (bytes < 0) { |
| 275 Die("%s: Unable to read from '%s'. Failed with error: %s", program_name, | 276 Die("%s: Unable to read from '%s'. Failed with error: %s", program_name, |
| 276 fletch_config_file, strerror(errno)); | 277 dartino_config_file, strerror(errno)); |
| 277 } else if (bytes == 0) { | 278 } else if (bytes == 0) { |
| 278 break; // End of file. | 279 break; // End of file. |
| 279 } | 280 } |
| 280 offset += bytes; | 281 offset += bytes; |
| 281 } | 282 } |
| 282 buffer[offset] = '\0'; | 283 buffer[offset] = '\0'; |
| 283 fletch_socket_port = atoi(buffer); | 284 dartino_socket_port = atoi(buffer); |
| 284 } | 285 } |
| 285 | 286 |
| 286 static void ComputeFletchRoot(char* buffer, size_t buffer_length) { | 287 static void ComputeDartinoRoot(char* buffer, size_t buffer_length) { |
| 287 // TODO(ahe): Fix lint problem: Do not use variable-length arrays. | 288 // TODO(ahe): Fix lint problem: Do not use variable-length arrays. |
| 288 char resolved[buffer_length]; // NOLINT | 289 char resolved[buffer_length]; // NOLINT |
| 289 GetPathOfExecutable(buffer, buffer_length); | 290 GetPathOfExecutable(buffer, buffer_length); |
| 290 if (realpath(buffer, resolved) == NULL) { | 291 if (realpath(buffer, resolved) == NULL) { |
| 291 Die("%s: realpath of '%s' failed: %s", program_name, buffer, | 292 Die("%s: realpath of '%s' failed: %s", program_name, buffer, |
| 292 strerror(errno)); | 293 strerror(errno)); |
| 293 } | 294 } |
| 294 StrCpy(buffer, buffer_length, resolved, sizeof(resolved)); | 295 StrCpy(buffer, buffer_length, resolved, sizeof(resolved)); |
| 295 | 296 |
| 296 // 'buffer' is now the absolute path of this executable (with symlinks | 297 // 'buffer' is now the absolute path of this executable (with symlinks |
| 297 // resolved). When running from fletch-repo, this executable will be in | 298 // resolved). When running from dartino-repo, this executable will be in |
| 298 // "fletch-repo/fletch/out/$CONFIGURATION/fletch". | 299 // "dartino-repo/dartino/out/$CONFIGURATION/dartino". |
| 299 ParentDir(buffer); | 300 ParentDir(buffer); |
| 300 // 'buffer' is now, for example, "fletch-repo/fletch/out/$CONFIGURATION". | 301 // 'buffer' is now, for example, "dartino-repo/dartino/out/$CONFIGURATION". |
| 301 | 302 |
| 302 // FLETCH_ROOT_DISTANCE gives the number of directories up that we find the | 303 // DARTINO_ROOT_DISTANCE gives the number of directories up that we find the |
| 303 // root of the fletch checkout or sdk bundle. | 304 // root of the dartino checkout or sdk bundle. |
| 304 for (int i = 0; i < FLETCH_ROOT_DISTANCE; i++) { | 305 for (int i = 0; i < DARTINO_ROOT_DISTANCE; i++) { |
| 305 ParentDir(buffer); | 306 ParentDir(buffer); |
| 306 } | 307 } |
| 307 | 308 |
| 308 size_t length = strlen(buffer); | 309 size_t length = strlen(buffer); |
| 309 if (length > 0 && buffer[length - 1] != '/') { | 310 if (length > 0 && buffer[length - 1] != '/') { |
| 310 // Append trailing slash. | 311 // Append trailing slash. |
| 311 StrCat(buffer, buffer_length, "/", 2); | 312 StrCat(buffer, buffer_length, "/", 2); |
| 312 } | 313 } |
| 313 } | 314 } |
| 314 | 315 |
| 315 static void GetExecutableDir(char* buffer, size_t buffer_length) { | 316 static void GetExecutableDir(char* buffer, size_t buffer_length) { |
| 316 // TODO(ahe): Fix lint problem: Do not use variable-length arrays. | 317 // TODO(ahe): Fix lint problem: Do not use variable-length arrays. |
| 317 char resolved[buffer_length]; // NOLINT | 318 char resolved[buffer_length]; // NOLINT |
| 318 GetPathOfExecutable(buffer, buffer_length); | 319 GetPathOfExecutable(buffer, buffer_length); |
| 319 if (realpath(buffer, resolved) == NULL) { | 320 if (realpath(buffer, resolved) == NULL) { |
| 320 Die("%s: realpath of '%s' failed: %s", program_name, buffer, | 321 Die("%s: realpath of '%s' failed: %s", program_name, buffer, |
| 321 strerror(errno)); | 322 strerror(errno)); |
| 322 } | 323 } |
| 323 StrCpy(buffer, buffer_length, resolved, sizeof(resolved)); | 324 StrCpy(buffer, buffer_length, resolved, sizeof(resolved)); |
| 324 | 325 |
| 325 // 'buffer' is now the absolute path of this executable (with symlinks | 326 // 'buffer' is now the absolute path of this executable (with symlinks |
| 326 // resolved). When running from fletch-repo, this executable will be in | 327 // resolved). When running from dartino-repo, this executable will be in |
| 327 // "fletch-repo/fletch/out/$CONFIGURATION/fletch". | 328 // "dartino-repo/dartino/out/$CONFIGURATION/dartino". |
| 328 ParentDir(buffer); | 329 ParentDir(buffer); |
| 329 // 'buffer' is now, for example, "fletch-repo/fletch/out/$CONFIGURATION". | 330 // 'buffer' is now, for example, "dartino-repo/dartino/out/$CONFIGURATION". |
| 330 | 331 |
| 331 size_t length = strlen(buffer); | 332 size_t length = strlen(buffer); |
| 332 if (length > 0 && buffer[length - 1] != '/') { | 333 if (length > 0 && buffer[length - 1] != '/') { |
| 333 // Append trailing slash. | 334 // Append trailing slash. |
| 334 StrCat(buffer, buffer_length, "/", 2); | 335 StrCat(buffer, buffer_length, "/", 2); |
| 335 } | 336 } |
| 336 } | 337 } |
| 337 | 338 |
| 338 // Stores the location of the Dart VM in 'buffer'. | 339 // Stores the location of the Dart VM in 'buffer'. |
| 339 static void ComputeDartVmPath(char* buffer, size_t buffer_length) { | 340 static void ComputeDartVmPath(char* buffer, size_t buffer_length) { |
| 340 char* dart_vm_env = getenv(dart_vm_env_name); | 341 char* dart_vm_env = getenv(dart_vm_env_name); |
| 341 if (dart_vm_env != NULL) { | 342 if (dart_vm_env != NULL) { |
| 342 if (realpath(dart_vm_env, buffer) == NULL) { | 343 if (realpath(dart_vm_env, buffer) == NULL) { |
| 343 Die("%s: realpath of '%s' failed: %s", program_name, dart_vm_env, | 344 Die("%s: realpath of '%s' failed: %s", program_name, dart_vm_env, |
| 344 strerror(errno)); | 345 strerror(errno)); |
| 345 } | 346 } |
| 346 return; | 347 return; |
| 347 } | 348 } |
| 348 | 349 |
| 349 GetExecutableDir(buffer, buffer_length); | 350 GetExecutableDir(buffer, buffer_length); |
| 350 StrCat(buffer, buffer_length, DART_VM_NAME, sizeof(DART_VM_NAME)); | 351 StrCat(buffer, buffer_length, DART_VM_NAME, sizeof(DART_VM_NAME)); |
| 351 // 'buffer' is now, for example, "fletch-repo/fletch/out/$CONFIGURATION/dart". | 352 // 'buffer' is now, for example, |
| 353 // "dartino-repo/dartino/out/$CONFIGURATION/dart". |
| 352 } | 354 } |
| 353 | 355 |
| 354 // Stores the location of the Fletch VM in 'buffer'. | 356 // Stores the location of the Dartino VM in 'buffer'. |
| 355 static void ComputeFletchVmPath(char* buffer, size_t buffer_length) { | 357 static void ComputeDartinoVmPath(char* buffer, size_t buffer_length) { |
| 356 GetExecutableDir(buffer, buffer_length); | 358 GetExecutableDir(buffer, buffer_length); |
| 357 | 359 |
| 358 StrCat(buffer, buffer_length, "fletch-vm", sizeof("fletch-vm")); | 360 StrCat(buffer, buffer_length, "dartino-vm", sizeof("dartino-vm")); |
| 359 // 'buffer' is now, for example, "fletch-repo/fletch/out/$CONFIGURATION/dart". | 361 // 'buffer' is now, for example, |
| 362 // "dartino-repo/dartino/out/$CONFIGURATION/dart". |
| 360 } | 363 } |
| 361 | 364 |
| 362 // Stores the package root in 'buffer'. The value of 'fletch_root' must be the | 365 // Stores the package root in 'buffer'. The value of 'dartino_root' must be the |
| 363 // absolute path of '.../fletch-repo/fletch/' (including trailing slash). | 366 // absolute path of '.../dartino-repo/dartino/' (including trailing slash). |
| 364 static void ComputePackageSpec(char* buffer, size_t buffer_length, | 367 static void ComputePackageSpec(char* buffer, size_t buffer_length, |
| 365 const char* fletch_root, | 368 const char* dartino_root, |
| 366 size_t fletch_root_length) { | 369 size_t dartino_root_length) { |
| 367 StrCpy(buffer, buffer_length, fletch_root, fletch_root_length); | 370 StrCpy(buffer, buffer_length, dartino_root, dartino_root_length); |
| 368 StrCat(buffer, buffer_length, FLETCHC_PKG_FILE, sizeof(FLETCHC_PKG_FILE)); | 371 StrCat(buffer, buffer_length, DARTINOC_PKG_FILE, sizeof(DARTINOC_PKG_FILE)); |
| 369 // 'buffer' is now, for example, "fletch-repo/fletch/package/". | 372 // 'buffer' is now, for example, "dartino-repo/dartino/package/". |
| 370 } | 373 } |
| 371 | 374 |
| 372 // Flush all open streams (FILE objects). This is needed before forking | 375 // Flush all open streams (FILE objects). This is needed before forking |
| 373 // (otherwise, buffered data will get duplicated in the children leading to | 376 // (otherwise, buffered data will get duplicated in the children leading to |
| 374 // duplicated output). It is also needed before using file descriptors, as I/O | 377 // duplicated output). It is also needed before using file descriptors, as I/O |
| 375 // based on file descriptors bypass any buffering in streams. | 378 // based on file descriptors bypass any buffering in streams. |
| 376 void FlushAllStreams() { | 379 void FlushAllStreams() { |
| 377 if (fflush(NULL) != 0) { | 380 if (fflush(NULL) != 0) { |
| 378 Die("%s: fflush failed: %s", program_name, strerror(errno)); | 381 Die("%s: fflush failed: %s", program_name, strerror(errno)); |
| 379 } | 382 } |
| (...skipping 11 matching lines...) Expand all Loading... |
| 391 | 394 |
| 392 static void WaitForDaemonHandshake(pid_t pid, int parent_stdout, | 395 static void WaitForDaemonHandshake(pid_t pid, int parent_stdout, |
| 393 int parent_stderr); | 396 int parent_stderr); |
| 394 | 397 |
| 395 static void ExecDaemon(int child_stdout, int child_stderr, const char** argv); | 398 static void ExecDaemon(int child_stdout, int child_stderr, const char** argv); |
| 396 | 399 |
| 397 static void StartDriverDaemon() { | 400 static void StartDriverDaemon() { |
| 398 const int kMaxArgv = 9; | 401 const int kMaxArgv = 9; |
| 399 const char* argv[kMaxArgv]; | 402 const char* argv[kMaxArgv]; |
| 400 | 403 |
| 401 char fletch_root[MAXPATHLEN + 1]; | 404 char dartino_root[MAXPATHLEN + 1]; |
| 402 ComputeFletchRoot(fletch_root, sizeof(fletch_root)); | 405 ComputeDartinoRoot(dartino_root, sizeof(dartino_root)); |
| 403 | 406 |
| 404 char vm_path[MAXPATHLEN + 1]; | 407 char vm_path[MAXPATHLEN + 1]; |
| 405 ComputeDartVmPath(vm_path, sizeof(vm_path)); | 408 ComputeDartVmPath(vm_path, sizeof(vm_path)); |
| 406 | 409 |
| 407 char fletch_vm_path[MAXPATHLEN + 1]; | 410 char dartino_vm_path[MAXPATHLEN + 1]; |
| 408 ComputeFletchVmPath(fletch_vm_path, sizeof(fletch_vm_path)); | 411 ComputeDartinoVmPath(dartino_vm_path, sizeof(dartino_vm_path)); |
| 409 | 412 |
| 410 char fletch_vm_option[sizeof("-Dfletch-vm=") + MAXPATHLEN + 1]; | 413 char dartino_vm_option[sizeof("-Ddartino-vm=") + MAXPATHLEN + 1]; |
| 411 StrCpy(fletch_vm_option, sizeof(fletch_vm_option), "-Dfletch-vm=", | 414 StrCpy(dartino_vm_option, sizeof(dartino_vm_option), "-Ddartino-vm=", |
| 412 sizeof("-Dfletch-vm=")); | 415 sizeof("-Ddartino-vm=")); |
| 413 StrCat(fletch_vm_option, sizeof(fletch_vm_option), fletch_vm_path, | 416 StrCat(dartino_vm_option, sizeof(dartino_vm_option), dartino_vm_path, |
| 414 sizeof(fletch_vm_path)); | 417 sizeof(dartino_vm_path)); |
| 415 | 418 |
| 416 char package_spec[MAXPATHLEN + 1]; | 419 char package_spec[MAXPATHLEN + 1]; |
| 417 ComputePackageSpec(package_spec, sizeof(package_spec), fletch_root, | 420 ComputePackageSpec(package_spec, sizeof(package_spec), dartino_root, |
| 418 sizeof(fletch_root)); | 421 sizeof(dartino_root)); |
| 419 char package_option[sizeof("--packages=") + MAXPATHLEN + 1]; | 422 char package_option[sizeof("--packages=") + MAXPATHLEN + 1]; |
| 420 StrCpy(package_option, sizeof(package_option), "--packages=", | 423 StrCpy(package_option, sizeof(package_option), "--packages=", |
| 421 sizeof("--packages=")); | 424 sizeof("--packages=")); |
| 422 StrCat(package_option, sizeof(package_option), package_spec, | 425 StrCat(package_option, sizeof(package_option), package_spec, |
| 423 sizeof(package_spec)); | 426 sizeof(package_spec)); |
| 424 | 427 |
| 425 const char library_root[] = "-Dfletchc-library-root=" FLETCHC_LIBRARY_ROOT; | 428 const char library_root[] = |
| 426 const char define_version[] = "-Dfletch.version="; | 429 "-Ddartino_compiler-library-root=" DARTINOC_LIBRARY_ROOT; |
| 430 const char define_version[] = "-Ddartino.version="; |
| 427 const char* version = GetVersion(); | 431 const char* version = GetVersion(); |
| 428 int version_option_length = sizeof(define_version) + strlen(version) + 1; | 432 int version_option_length = sizeof(define_version) + strlen(version) + 1; |
| 429 char* version_option = StrAlloc(version_option_length); | 433 char* version_option = StrAlloc(version_option_length); |
| 430 StrCpy(version_option, version_option_length, define_version, | 434 StrCpy(version_option, version_option_length, define_version, |
| 431 sizeof(define_version)); | 435 sizeof(define_version)); |
| 432 StrCat(version_option, version_option_length, version, strlen(version) + 1); | 436 StrCat(version_option, version_option_length, version, strlen(version) + 1); |
| 433 | 437 |
| 434 int argc = 0; | 438 int argc = 0; |
| 435 argv[argc++] = vm_path; | 439 argv[argc++] = vm_path; |
| 436 argv[argc++] = "-c"; | 440 argv[argc++] = "-c"; |
| 437 argv[argc++] = fletch_vm_option; | 441 argv[argc++] = dartino_vm_option; |
| 438 argv[argc++] = package_option; | 442 argv[argc++] = package_option; |
| 439 argv[argc++] = version_option; | 443 argv[argc++] = version_option; |
| 440 argv[argc++] = library_root; | 444 argv[argc++] = library_root; |
| 441 argv[argc++] = "package:fletchc/src/hub/hub_main.dart"; | 445 argv[argc++] = "package:dartino_compiler/src/hub/hub_main.dart"; |
| 442 argv[argc++] = fletch_config_file; | 446 argv[argc++] = dartino_config_file; |
| 443 argv[argc++] = NULL; | 447 argv[argc++] = NULL; |
| 444 if (argc > kMaxArgv) Die("Internal error: increase argv size"); | 448 if (argc > kMaxArgv) Die("Internal error: increase argv size"); |
| 445 | 449 |
| 446 int file_descriptors[2]; | 450 int file_descriptors[2]; |
| 447 if (pipe(file_descriptors) != 0) { | 451 if (pipe(file_descriptors) != 0) { |
| 448 Die("%s: pipe failed: %s", program_name, strerror(errno)); | 452 Die("%s: pipe failed: %s", program_name, strerror(errno)); |
| 449 } | 453 } |
| 450 int parent_stdout = file_descriptors[0]; | 454 int parent_stdout = file_descriptors[0]; |
| 451 int child_stdout = file_descriptors[1]; | 455 int child_stdout = file_descriptors[1]; |
| 452 | 456 |
| 453 if (pipe(file_descriptors) != 0) { | 457 if (pipe(file_descriptors) != 0) { |
| 454 Die("%s: pipe failed: %s", program_name, strerror(errno)); | 458 Die("%s: pipe failed: %s", program_name, strerror(errno)); |
| 455 } | 459 } |
| 456 int parent_stderr = file_descriptors[0]; | 460 int parent_stderr = file_descriptors[0]; |
| 457 int child_stderr = file_descriptors[1]; | 461 int child_stderr = file_descriptors[1]; |
| 458 | 462 |
| 459 pid_t pid = Fork(); | 463 pid_t pid = Fork(); |
| 460 if (pid == 0) { | 464 if (pid == 0) { |
| 461 // In child. | 465 // In child. |
| 462 Close(parent_stdout); | 466 Close(parent_stdout); |
| 463 Close(parent_stderr); | 467 Close(parent_stderr); |
| 464 Close(fletch_config_fd); | 468 Close(dartino_config_fd); |
| 465 ExecDaemon(child_stdout, child_stderr, argv); | 469 ExecDaemon(child_stdout, child_stderr, argv); |
| 466 UNREACHABLE(); | 470 UNREACHABLE(); |
| 467 } else { | 471 } else { |
| 468 free(version_option); | 472 free(version_option); |
| 469 Close(child_stdout); | 473 Close(child_stdout); |
| 470 Close(child_stderr); | 474 Close(child_stderr); |
| 471 WaitForDaemonHandshake(pid, parent_stdout, parent_stderr); | 475 WaitForDaemonHandshake(pid, parent_stdout, parent_stderr); |
| 472 } | 476 } |
| 473 } | 477 } |
| 474 | 478 |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 598 if (match != NULL) { | 602 if (match != NULL) { |
| 599 // If we do not have a precise match the VM is printing | 603 // If we do not have a precise match the VM is printing |
| 600 // something unexpected and we print it out to make | 604 // something unexpected and we print it out to make |
| 601 // debugging easier. | 605 // debugging easier. |
| 602 if (match[1] != '\0') { | 606 if (match[1] != '\0') { |
| 603 FlushAllStreams(); | 607 FlushAllStreams(); |
| 604 WriteFully(STDOUT_FILENO, reinterpret_cast<uint8*>(buffer), | 608 WriteFully(STDOUT_FILENO, reinterpret_cast<uint8*>(buffer), |
| 605 bytes_read); | 609 bytes_read); |
| 606 } | 610 } |
| 607 match[0] = '\0'; | 611 match[0] = '\0'; |
| 608 fletch_socket_port = atoi(stdout_buffer); | 612 dartino_socket_port = atoi(stdout_buffer); |
| 609 // We got the server handshake (the port). So we break to | 613 // We got the server handshake (the port). So we break to |
| 610 // eventually return from this function. | 614 // eventually return from this function. |
| 611 break; | 615 break; |
| 612 } | 616 } |
| 613 } | 617 } |
| 614 } | 618 } |
| 615 } | 619 } |
| 616 Close(parent_stdout); | 620 Close(parent_stdout); |
| 617 Close(parent_stderr); | 621 Close(parent_stderr); |
| 618 } | 622 } |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 706 | 710 |
| 707 Die("%s: Unhandled command code: %i\n", program_name, command); | 711 Die("%s: Unhandled command code: %i\n", program_name, command); |
| 708 return DriverConnection::kDriverConnectionError; | 712 return DriverConnection::kDriverConnectionError; |
| 709 } | 713 } |
| 710 | 714 |
| 711 Socket* Connect() { | 715 Socket* Connect() { |
| 712 struct sockaddr_in address; | 716 struct sockaddr_in address; |
| 713 | 717 |
| 714 address.sin_family = AF_INET; | 718 address.sin_family = AF_INET; |
| 715 inet_pton(AF_INET, "127.0.0.1", &address.sin_addr); | 719 inet_pton(AF_INET, "127.0.0.1", &address.sin_addr); |
| 716 address.sin_port = htons(fletch_socket_port); | 720 address.sin_port = htons(dartino_socket_port); |
| 717 | 721 |
| 718 int fd = socket(PF_INET, SOCK_STREAM, 0); | 722 int fd = socket(PF_INET, SOCK_STREAM, 0); |
| 719 if (fd < 0) { | 723 if (fd < 0) { |
| 720 Die("%s: socket failed: %s", program_name, strerror(errno)); | 724 Die("%s: socket failed: %s", program_name, strerror(errno)); |
| 721 } | 725 } |
| 722 Socket* socket = Socket::FromFd(fd); | 726 Socket* socket = Socket::FromFd(fd); |
| 723 | 727 |
| 724 int connect_result = TEMP_FAILURE_RETRY(connect( | 728 int connect_result = TEMP_FAILURE_RETRY(connect( |
| 725 fd, reinterpret_cast<struct sockaddr*>(&address), sizeof(address))); | 729 fd, reinterpret_cast<struct sockaddr*>(&address), sizeof(address))); |
| 726 if (connect_result != 0) { | 730 if (connect_result != 0) { |
| (...skipping 29 matching lines...) Expand all Loading... |
| 756 // process hasn't exited after 2 seconds. | 760 // process hasn't exited after 2 seconds. |
| 757 // The process is identified using lsof on the Dart VM binary. | 761 // The process is identified using lsof on the Dart VM binary. |
| 758 static int QuitCommand() { | 762 static int QuitCommand() { |
| 759 const int MAX_COMMAND_LENGTH = 256; | 763 const int MAX_COMMAND_LENGTH = 256; |
| 760 char command[MAX_COMMAND_LENGTH]; | 764 char command[MAX_COMMAND_LENGTH]; |
| 761 // We used exec to avoid having pkill the /bin/sh parent process it is running | 765 // We used exec to avoid having pkill the /bin/sh parent process it is running |
| 762 // as a child of when redirecting to /dev/null. | 766 // as a child of when redirecting to /dev/null. |
| 763 const char pkill[] = "exec pkill -f "; | 767 const char pkill[] = "exec pkill -f "; |
| 764 const char pkill_force[] = "exec pkill -KILL -f "; | 768 const char pkill_force[] = "exec pkill -KILL -f "; |
| 765 const char driver_arguments[] = | 769 const char driver_arguments[] = |
| 766 "package:fletchc/src/driver/driver_main > /dev/null"; | 770 "package:dartino_compiler/src/driver/driver_main > /dev/null"; |
| 767 const char hub_arguments[] = "package:fletchc/src/hub/hub_main > /dev/null"; | 771 const char hub_arguments[] = |
| 772 "package:dartino_compiler/src/hub/hub_main > /dev/null"; |
| 768 | 773 |
| 769 StrCpy(command, MAX_COMMAND_LENGTH, pkill, sizeof(pkill)); | 774 StrCpy(command, MAX_COMMAND_LENGTH, pkill, sizeof(pkill)); |
| 770 StrCat(command, MAX_COMMAND_LENGTH, hub_arguments, sizeof(hub_arguments)); | 775 StrCat(command, MAX_COMMAND_LENGTH, hub_arguments, sizeof(hub_arguments)); |
| 771 | 776 |
| 772 const char* current_arguments = hub_arguments; | 777 const char* current_arguments = hub_arguments; |
| 773 // pkill -f package:fletchc/src/hub/hub_main | 778 // pkill -f package:dartino_compiler/src/hub/hub_main |
| 774 if (CheckedSystem(command) != 0) { | 779 if (CheckedSystem(command) != 0) { |
| 775 // pkill returns 0 if it killed any processes, so in this case it didn't | 780 // pkill returns 0 if it killed any processes, so in this case it didn't |
| 776 // find/kill any active persistent processes | 781 // find/kill any active persistent processes |
| 777 // Try with the legacy driver_main path to see if an old persistent process | 782 // Try with the legacy driver_main path to see if an old persistent process |
| 778 // was running. | 783 // was running. |
| 779 StrCpy(command, MAX_COMMAND_LENGTH, pkill, sizeof(pkill)); | 784 StrCpy(command, MAX_COMMAND_LENGTH, pkill, sizeof(pkill)); |
| 780 StrCat(command, MAX_COMMAND_LENGTH, driver_arguments, | 785 StrCat(command, MAX_COMMAND_LENGTH, driver_arguments, |
| 781 sizeof(driver_arguments)); | 786 sizeof(driver_arguments)); |
| 782 // pkill -f package:fletchc/src/driver/driver_main | 787 // pkill -f package:dartino_compiler/src/driver/driver_main |
| 783 if (CheckedSystem(command) != 0) { | 788 if (CheckedSystem(command) != 0) { |
| 784 // No legacy persistent process. Just remove the socket location file. | 789 // No legacy persistent process. Just remove the socket location file. |
| 785 unlink(fletch_config_file); | 790 unlink(dartino_config_file); |
| 786 printf("Background process wasn't running\n"); | 791 printf("Background process wasn't running\n"); |
| 787 return 0; | 792 return 0; |
| 788 } | 793 } |
| 789 current_arguments = driver_arguments; | 794 current_arguments = driver_arguments; |
| 790 } | 795 } |
| 791 | 796 |
| 792 // Wait two seconds for the process to exit gracefully. | 797 // Wait two seconds for the process to exit gracefully. |
| 793 sleep(2); | 798 sleep(2); |
| 794 | 799 |
| 795 // Remove the socket location file. | 800 // Remove the socket location file. |
| 796 unlink(fletch_config_file); | 801 unlink(dartino_config_file); |
| 797 | 802 |
| 798 // To check if the process exited gracefully we try to kill it again | 803 // To check if the process exited gracefully we try to kill it again |
| 799 // (this time with SIGKILL). If that command doesn't find any running | 804 // (this time with SIGKILL). If that command doesn't find any running |
| 800 // processes it will return 1. If it finds one or more running instance | 805 // processes it will return 1. If it finds one or more running instance |
| 801 // it returns 0 in which case we know it didn't shutdown gracefully above. | 806 // it returns 0 in which case we know it didn't shutdown gracefully above. |
| 802 // We use the return value to decide what to report to the user. | 807 // We use the return value to decide what to report to the user. |
| 803 StrCpy(command, MAX_COMMAND_LENGTH, pkill_force, sizeof(pkill_force)); | 808 StrCpy(command, MAX_COMMAND_LENGTH, pkill_force, sizeof(pkill_force)); |
| 804 StrCat(command, MAX_COMMAND_LENGTH, current_arguments, | 809 StrCat(command, MAX_COMMAND_LENGTH, current_arguments, |
| 805 strlen(current_arguments) + 1); | 810 strlen(current_arguments) + 1); |
| 806 | 811 |
| 807 // pkill -KILL -f package:fletchc/src/hub/hub_main or | 812 // pkill -KILL -f package:dartino_compiler/src/hub/hub_main or |
| 808 // pkill -KILL -f package:fletchc/src/driver/driver_main depending on the | 813 // pkill -KILL -f package:dartino_compiler/src/driver/driver_main depending |
| 809 // above pkill. | 814 // on the above pkill. |
| 810 if (CheckedSystem(command) != 0) { | 815 if (CheckedSystem(command) != 0) { |
| 811 // We assume it didn't find any processes to kill when returning a | 816 // We assume it didn't find any processes to kill when returning a |
| 812 // non-zero value and hence just report the process gracefully exited. | 817 // non-zero value and hence just report the process gracefully exited. |
| 813 printf("Background process exited\n"); | 818 printf("Background process exited\n"); |
| 814 } else { | 819 } else { |
| 815 printf( | 820 printf( |
| 816 "The background process didn't exit after 2 seconds. " | 821 "The background process didn't exit after 2 seconds. " |
| 817 "Forcefully quit the background process.\n"); | 822 "Forcefully quit the background process.\n"); |
| 818 } | 823 } |
| 819 return 0; | 824 return 0; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 830 return QuitCommand(); | 835 return QuitCommand(); |
| 831 } | 836 } |
| 832 | 837 |
| 833 Socket* control_socket = Connect(); | 838 Socket* control_socket = Connect(); |
| 834 if (control_socket == NULL) { | 839 if (control_socket == NULL) { |
| 835 StartDriverDaemon(); | 840 StartDriverDaemon(); |
| 836 | 841 |
| 837 control_socket = Connect(); | 842 control_socket = Connect(); |
| 838 if (control_socket == NULL) { | 843 if (control_socket == NULL) { |
| 839 Die( | 844 Die( |
| 840 "%s: Failed to start fletch server (%s).\n" | 845 "%s: Failed to start dartino server (%s).\n" |
| 841 "Use DART_VM environment variable to override location of Dart VM.", | 846 "Use DART_VM environment variable to override location of Dart VM.", |
| 842 program_name, strerror(errno)); | 847 program_name, strerror(errno)); |
| 843 } | 848 } |
| 844 } | 849 } |
| 845 | 850 |
| 846 UnlockConfigFile(); | 851 UnlockConfigFile(); |
| 847 | 852 |
| 848 int signal_pipe = SignalFileDescriptor(); | 853 int signal_pipe = SignalFileDescriptor(); |
| 849 | 854 |
| 850 DriverConnection* connection = new DriverConnection(control_socket); | 855 DriverConnection* connection = new DriverConnection(control_socket); |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 903 break; | 908 break; |
| 904 } | 909 } |
| 905 } | 910 } |
| 906 } | 911 } |
| 907 } | 912 } |
| 908 | 913 |
| 909 Exit(exit_code); | 914 Exit(exit_code); |
| 910 return exit_code; | 915 return exit_code; |
| 911 } | 916 } |
| 912 | 917 |
| 913 } // namespace fletch | 918 } // namespace dartino |
| 914 | 919 |
| 915 // Forward main calls to fletch::Main. | 920 // Forward main calls to dartino::Main. |
| 916 int main(int argc, char** argv) { return fletch::Main(argc, argv); } | 921 int main(int argc, char** argv) { return dartino::Main(argc, argv); } |
| OLD | NEW |