summaryrefslogtreecommitdiff
path: root/src/couchdb/priv
diff options
context:
space:
mode:
authorPaul Joseph Davis <davisp@apache.org>2009-08-18 01:27:03 +0000
committerPaul Joseph Davis <davisp@apache.org>2009-08-18 01:27:03 +0000
commit39a629b0d63ca675bd24844c924203d30bd3ba9b (patch)
tree3071af152be6485e53853551fa8c6e967b5e31ba /src/couchdb/priv
parentf723cb99008f2462abec46ab9b614fb8dd2f31d1 (diff)
Applying markh's Windows build patch.
Fixes COUCHDB-406 git-svn-id: https://svn.apache.org/repos/asf/couchdb/trunk@805243 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src/couchdb/priv')
-rwxr-xr-xsrc/couchdb/priv/couchspawnkillable.sh (renamed from src/couchdb/priv/couchspawnkillable)0
-rw-r--r--src/couchdb/priv/couchspawnkillable_win.c139
2 files changed, 139 insertions, 0 deletions
diff --git a/src/couchdb/priv/couchspawnkillable b/src/couchdb/priv/couchspawnkillable.sh
index f8d042e3..f8d042e3 100755
--- a/src/couchdb/priv/couchspawnkillable
+++ b/src/couchdb/priv/couchspawnkillable.sh
diff --git a/src/couchdb/priv/couchspawnkillable_win.c b/src/couchdb/priv/couchspawnkillable_win.c
new file mode 100644
index 00000000..f812711e
--- /dev/null
+++ b/src/couchdb/priv/couchspawnkillable_win.c
@@ -0,0 +1,139 @@
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+// Do what 2 lines of shell script in couchspawnkillable does...
+// * Create a new suspended process with the same (duplicated) standard
+// handles as us.
+// * Write a line to stdout, consisting of the path to ourselves, plus
+// '--kill {pid}' where {pid} is the PID of the newly created process.
+// * Un-suspend the new process.
+// * Terminate
+
+// Later, couch will call us with --kill and the PID, so we dutifully
+// terminate the specified PID.
+
+#include <stdlib.h>
+#include "windows.h"
+
+char *get_child_cmdline(int argc, char **argv)
+{
+ // make a new command-line, but skipping me.
+ // XXX - todo - spaces etc in args???
+ int i;
+ char *p, *cmdline;
+ int nchars = 0;
+ int nthis = 1;
+ for (i=1;i<argc;i++)
+ nchars += strlen(argv[i])+1;
+ cmdline = p = malloc(nchars+1);
+ if (!cmdline)
+ return NULL;
+ for (i=1;i<argc;i++) {
+ nthis = strlen(argv[i]);
+ strncpy(p, argv[i], nthis);
+ p[nthis] = ' ';
+ p += nthis+1;
+ }
+ // Replace the last space we added above with a '\0'
+ cmdline[nchars-1] = '\0';
+ return cmdline;
+}
+
+// create the child process, returning 0, or the exit-code we will
+// terminate with.
+int create_child(int argc, char **argv, PROCESS_INFORMATION *pi)
+{
+ char buf[1024];
+ DWORD dwcreate;
+ STARTUPINFO si;
+ char *cmdline;
+ if (argc < 2)
+ return 1;
+ cmdline = get_child_cmdline(argc, argv);
+ if (!cmdline)
+ return 2;
+
+ memset(&si, 0, sizeof(si));
+ si.cb = sizeof(si);
+ // depending on how *our* parent is started, we may or may not have
+ // a valid stderr stream - so although we try and duplicate it, only
+ // failing to duplicate stdin and stdout are considered fatal.
+ if (!DuplicateHandle(GetCurrentProcess(),
+ GetStdHandle(STD_INPUT_HANDLE),
+ GetCurrentProcess(),
+ &si.hStdInput,
+ 0,
+ TRUE, // inheritable
+ DUPLICATE_SAME_ACCESS) ||
+ !DuplicateHandle(GetCurrentProcess(),
+ GetStdHandle(STD_OUTPUT_HANDLE),
+ GetCurrentProcess(),
+ &si.hStdOutput,
+ 0,
+ TRUE, // inheritable
+ DUPLICATE_SAME_ACCESS)) {
+ return 3;
+ }
+ DuplicateHandle(GetCurrentProcess(),
+ GetStdHandle(STD_ERROR_HANDLE),
+ GetCurrentProcess(),
+ &si.hStdError,
+ 0,
+ TRUE, // inheritable
+ DUPLICATE_SAME_ACCESS);
+
+ si.dwFlags = STARTF_USESTDHANDLES;
+ dwcreate = CREATE_SUSPENDED;
+ if (!CreateProcess( NULL, cmdline,
+ NULL,
+ NULL,
+ TRUE, // inherit handles
+ dwcreate,
+ NULL, // environ
+ NULL, // cwd
+ &si,
+ pi))
+ return 4;
+ return 0;
+}
+
+// and here we go...
+int main(int argc, char **argv)
+{
+ char out_buf[1024];
+ int rc;
+ DWORD cbwritten;
+ PROCESS_INFORMATION pi;
+ if (argc==3 && strcmp(argv[1], "--kill")==0) {
+ HANDLE h = OpenProcess(PROCESS_TERMINATE, 0, atoi(argv[2]));
+ if (!h)
+ return 1;
+ if (!TerminateProcess(h, 0))
+ return 2;
+ CloseHandle(h);
+ return 0;
+ }
+ // spawn the new suspended process
+ rc = create_child(argc, argv, &pi);
+ if (rc)
+ return rc;
+ // Write the 'terminate' command, which includes this PID, back to couch.
+ // *sob* - what about spaces etc?
+ sprintf_s(out_buf, sizeof(out_buf), "%s --kill %d\n",
+ argv[0], pi.dwProcessId);
+ WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), out_buf, strlen(out_buf),
+ &cbwritten, NULL);
+ // Let the child process go...
+ ResumeThread(pi.hThread);
+ // and that is all - we can die...
+ return 0;
+}