Created
February 20, 2014 22:04
-
-
Save talonsensei/9124230 to your computer and use it in GitHub Desktop.
Diff of launcher.cc from shiny-server showing the changes necessary to make it work on OS X. From https://github.com/nathanweeks/shiny-server/commit/d5240ef6d795dafc89c74a49d6f14d7fe0509541
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@@ -1,1 +1,1 @@ | |
/* | |
* launcher.cc | |
* | |
* Copyright (C) 2009-13 by RStudio, Inc. | |
* | |
* This program is licensed to you under the terms of version 3 of the | |
* GNU Affero General Public License. This program is distributed WITHOUT | |
* ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT, | |
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the | |
* AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details. | |
* | |
*/ | |
#include <unistd.h> | |
#include <sys/param.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <errno.h> | |
#include <libgen.h> | |
#include <string.h> | |
#include <sys/types.h> | |
#include <sys/stat.h> | |
#include <string> | |
#include <vector> | |
#include <algorithm> | |
+#ifdef __APPLE__ | |
+ #include <libproc.h> | |
+#endif | |
#include "launcher.h" | |
// The purpose of this executable is to provide a clean entry point for | |
// shiny-server, that is capable of running either daemonized or not. | |
int findBaseDir(std::string* shinyServerPath); | |
int main(int argc, char **argv) { | |
// If the caller requested daemonizing, do it. | |
for (int i = 1; i < argc; i++) { | |
if (strcmp(argv[i], "--daemonize") == 0) { | |
daemon(1, 0); | |
break; | |
} | |
} | |
std::string shinyServerPath; | |
int result = findBaseDir(&shinyServerPath); | |
if (result != 0) | |
return result; | |
std::string nodePath = shinyServerPath + "/ext/node/bin/shiny-server"; | |
std::string mainPath = shinyServerPath + "/lib/main.js"; | |
// Two extra args: one for mainPath, one for NULL terminator | |
char** newargs = new char*[argc + 2]; | |
newargs[0] = strdup(nodePath.c_str()); | |
newargs[1] = strdup(mainPath.c_str()); | |
for (int i = 0; i < argc - 1; i++) { | |
newargs[i + 2] = argv[i + 1]; | |
} | |
newargs[argc + 1] = NULL; | |
execv(nodePath.c_str(), newargs); | |
// This will actually never get called. | |
free(newargs[0]); | |
free(newargs[1]); | |
delete newargs; | |
return 0; | |
} | |
// Determines the base dir of the shiny-server instance that's being invoked, | |
// by calling readlink on /proc/<pid>/exe. | |
int findBaseDir(std::string* shinyServerPath) { | |
+#ifdef __APPLE__ | |
+ char execPath[PROC_PIDPATHINFO_MAXSIZE]; | |
+ if (!proc_pidpath(getpid(), execPath, sizeof(execPath))) { | |
+ perror("proc_pidpath"); | |
+ // unexpected error | |
+ return 2; | |
+ } | |
+#else // assuming Linux | |
char execPath[MAXPATHLEN + 1]; | |
int cn = snprintf(execPath, MAXPATHLEN + 1, "/proc/%d/exe", getpid()); | |
if (cn < 0 || cn > MAXPATHLEN) { | |
// Not expected | |
return 2; | |
} | |
struct stat execStat; | |
if (lstat(execPath, &execStat)) { | |
if (errno == ENOENT) | |
fprintf(stderr, "/proc/%d/exe doesn't exist--got Linux?\n", getpid()); | |
else | |
fprintf(stderr, "Fatal error calling lstat: %d\n", errno); | |
return 1; | |
} | |
if (!S_ISLNK(execStat.st_mode)) { | |
fprintf(stderr, "/proc/%d/exe was not a symlink\n", getpid()); | |
return 1; | |
} | |
if (execStat.st_size > MAXPATHLEN) { | |
fprintf(stderr, "Link resolved to an unexpectedly long path\n"); | |
return 1; | |
} | |
ssize_t charsNeeded = execStat.st_size > 0 ? execStat.st_size : MAXPATHLEN; | |
std::vector<char> execBuf(charsNeeded + 1, 0); | |
ssize_t cb = readlink(execPath, &execBuf[0], execBuf.size()); | |
if (cb < 0) { | |
fprintf(stderr, "Fatal error calling readlink: %d\n", errno); | |
return 1; | |
} | |
std::copy(execBuf.begin(), execBuf.begin() + cb, execPath); | |
execPath[cb] = '\0'; | |
- | |
+#endif | |
*shinyServerPath = dirname(dirname(execPath)); | |
return 0; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment