couchdb-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From dav...@apache.org
Subject svn commit: r805243 - in /couchdb/trunk: ./ bin/ etc/couchdb/ src/couchdb/ src/couchdb/priv/
Date Tue, 18 Aug 2009 01:27:04 GMT
Author: davisp
Date: Tue Aug 18 01:27:03 2009
New Revision: 805243

URL: http://svn.apache.org/viewvc?rev=805243&view=rev
Log:
Applying markh's Windows build patch.

Fixes COUCHDB-406


Added:
    couchdb/trunk/bin/couchdb.bat.tpl.in
    couchdb/trunk/src/couchdb/priv/couchspawnkillable.sh
      - copied unchanged from r805241, couchdb/trunk/src/couchdb/priv/couchspawnkillable
    couchdb/trunk/src/couchdb/priv/couchspawnkillable_win.c
Removed:
    couchdb/trunk/src/couchdb/priv/couchspawnkillable
Modified:
    couchdb/trunk/README
    couchdb/trunk/bin/   (props changed)
    couchdb/trunk/bin/Makefile.am
    couchdb/trunk/configure.ac
    couchdb/trunk/etc/couchdb/Makefile.am
    couchdb/trunk/src/couchdb/Makefile.am

Modified: couchdb/trunk/README
URL: http://svn.apache.org/viewvc/couchdb/trunk/README?rev=805243&r1=805242&r2=805243&view=diff
==============================================================================
--- couchdb/trunk/README (original)
+++ couchdb/trunk/README Tue Aug 18 01:27:03 2009
@@ -261,4 +261,143 @@
 Windows
 ~~~~~~~
 
-Windows documentation is incomplete. Please submit suggestions.
+The Windows build process is very similar to the erlang build process;
+indeed, we re-use some of their shell-scripts.  Therefore, it is recommended
+you build erlang itself from sources - this will ensure that you have all the
+tools and environment necessary to build couch itself.  A binary build of
+erlang should work for those in a hurry (see below), but it isn't really
+supported.  See the end of these notes or information on building erlang
+which is relevant to couch.
+
+Build Tools
+-----------
+
+To build on Windows, you need the following tools:
+
+* cygwin - it isn't clear exactly which tools you need - select all
+  'development' tools.  As mentioned above, if you can build erlang itself
+  you have everything you need.
+
+* VS2008
+
+* Erlang - a built source distro of erlang is preferred.  A binary
+  distribution of Erlang is OK, but you will also need a source distribution
+  for the cc.sh/link.sh etc wrapper shell scripts used by erlang - couch
+  reuses these scripts in its build process and the license isn't compatible
+  enough for us to clone them.
+
+Other tools:
+
+* Fetch the 'curl' sources and build them as per the instructions.  The cygwin
+  curl binaries are built with a different compiler so are no good.
+
+* Download the ICU binaries built with VS2008.
+
+* Download and build the same version of spidermonkey the version of couch
+  requires - at time of writing this is 1.8.  Different versions will not
+  work (ie, at time of writing, 1.8.1 does not work with couch).
+
+Build Environment
+-----------------
+
+Setup your environment:
+
+For the sake of everything you find sacred:
+  set CYGWIN=nontsec
+BEFORE starting any cygwin environments.  Set this variable globally.  Without
+it you can expect all kinds of permissions-related problems.
+
+Execute the VC .bat files to setup your environment such that cl.exe etc are
+on your path.  Start a cygwin shell.
+
+Check your environment:
+  * which link -> should point at the MS linker.
+  * which cl -> should point at the MS compiler.
+
+If you are building from a source version of erlang:
+
+  Executing  "eval `./otp_build env_win32`" as per the Erlang build
+  instructions, will have set everything up, including the CC, LD etc
+  variables.  Do this even if erlang is already built and you are just
+  building couch.  This will have set the variables ERL_TOP, CC, LD, AD
+  and a number of others.
+
+  Then, PATH must be adjusted such what 'which erl' lists the erl.exe
+  you built rather than the 'erl' script in the erts/etc/win32/cygwin_tools
+  directory - eg:
+
+  $ export PATH=$ERL_TOP/release/win32/erts-5.7.2/bin:$PATH
+
+If you are building from a binary version of erlang:
+
+  * set ERL_TOP to the top of the erlang directory
+
+  Add to the PATH such that 'which erl' points at your erl.exe - eg:
+
+  $ export PATH=$ERL_TOP/erts-5.6.5/bin
+
+  You must also ensure the cc.sh etc scripts from the Erlang source tree is
+  on your PATH.  Use "which cc.sh" to ensure the path is set correctly.
+
+  Then set more variables:
+    $ export CC=cc.sh
+    $ export LD=ld.sh
+    $ export AR=ar.sh
+    $ export RC=rc.sh
+
+Set COUCHDB_TOP to the source directory.
+
+And we should be ready to bootstrap and build.
+
+Building
+--------
+
+We start by bootstrapping:
+
+  $ cd $COUCHDB_TOP
+  $ ./bootstrap
+  You have bootstrapped Apache CouchDB, time to relax.
+
+  Run `./configure' to configure the source before you install.
+  $
+
+Relax.
+
+Now we need to run a complicated configure command-line.
+
+  $ ./configure \
+      --with-js-include=/cygdrive/c/path_to_seamonkey_include \
+      --with-js-lib=/cygdrive/c/path_to_seamonkey_lib \
+      --with-win32-icu-binaries=/cygdrive/c/path_to_icu_binaries_root \
+      --with-erlang=$ERL_TOP/release/win32/usr/include \
+      --with-win32-curl=/cygdrive/c/path/to/curl/root/directory
+      --prefix=$ERL_TOP/release/win32
+
+Note that all paths must be in cygwin format.  Those starting with $ERL_TOP
+can be entered literally, assuming ERL_TOP is set as described above.
+
+Relax on your new couch:
+
+  The $ERL_TOP/win32/release directory is now ready to .zip up, be packaged
+  by an installer, etc.  To test it in-place, execute:
+  
+  $ $ERL_TOP/win32/release/bin/couchdb.bat
+  
+  and everything should work fine.  
+
+Additional Notes:
+
+Building erlang: 
+* Follow the instructions as described.  You do need openssl, but don't need
+  the GUI tools.  You may like to execute:
+
+    echo "skipping gs" > lib/gs/SKIP
+    echo "skipping ic" > lib/ic/SKIP
+
+  To skip them.
+
+* Ensure 'which link' points at the ms linker; one in /usr/bin may be found
+  instead.
+
+* After executing './otp_build release -a', be sure to execute Install.exe in
+  the release/win32 directory to setup the release/win32/bin dir correctly.

Propchange: couchdb/trunk/bin/
------------------------------------------------------------------------------
--- svn:ignore (original)
+++ svn:ignore Tue Aug 18 01:27:03 2009
@@ -3,6 +3,7 @@
 couchdb
 couchdb.1
 couchdb.tpl
+couchdb.bat.tpl
 couchjs
 couchjs.1
 couchjs.tpl

Modified: couchdb/trunk/bin/Makefile.am
URL: http://svn.apache.org/viewvc/couchdb/trunk/bin/Makefile.am?rev=805243&r1=805242&r2=805243&view=diff
==============================================================================
--- couchdb/trunk/bin/Makefile.am (original)
+++ couchdb/trunk/bin/Makefile.am Tue Aug 18 01:27:03 2009
@@ -10,7 +10,12 @@
 ## License for the specific language governing permissions and limitations under
 ## the License.
 
+if WINDOWS
+bin_SCRIPTS = couchdb.bat
+else
 bin_SCRIPTS = couchdb couchjs
+endif
+
 noinst_SCRIPTS = couchjs_dev
 
 if HELP2MAN
@@ -69,6 +74,11 @@
 	$@ < $<
 	chmod +x $@
 
+couchdb.bat: couchdb.bat.tpl
+	sed -e "s|%ICU_CONFIG%|$(ICU_CONFIG)|g" \
+	    -e "s|%version%|@version@|g" \
+	$< > $@
+
 HELP2MAN_OPTION=--no-info --help-option="-h" --version-option="-V"
 
 # XXX: Because the scripts are made at build time for the user we need to

Added: couchdb/trunk/bin/couchdb.bat.tpl.in
URL: http://svn.apache.org/viewvc/couchdb/trunk/bin/couchdb.bat.tpl.in?rev=805243&view=auto
==============================================================================
--- couchdb/trunk/bin/couchdb.bat.tpl.in (added)
+++ couchdb/trunk/bin/couchdb.bat.tpl.in Tue Aug 18 01:27:03 2009
@@ -0,0 +1,14 @@
+@echo off
+setlocal
+rem First change to the erlang bin directory
+cd %~dp0
+
+rem Allow a different erlang executable (eg, werl) to be used.
+if "%ERL%x" == "x" set ERL=erl.exe
+
+echo CouchDB %version% - prepare to relax...
+%ERL% -smp auto -sasl errlog_type error ^
+      -eval "application:load(crypto)" ^
+      -eval "application:load(couch)" ^
+      -eval "crypto:start()" ^
+      -eval "couch_server:start([""../etc/couchdb/default.ini"", ""../etc/couchdb/local.ini""]),
receive done -> done end."

Modified: couchdb/trunk/configure.ac
URL: http://svn.apache.org/viewvc/couchdb/trunk/configure.ac?rev=805243&r1=805242&r2=805243&view=diff
==============================================================================
--- couchdb/trunk/configure.ac (original)
+++ couchdb/trunk/configure.ac Tue Aug 18 01:27:03 2009
@@ -80,17 +80,36 @@
 
 LIB_FLAGS="$JS_LIB_FLAGS -L/usr/local/lib -L/opt/local/lib"
 LIBS="$LIB_FLAGS $LIBS"
-# XP_UNIX required for jsapi.h and has been tested to work on Linux and Darwin.
-FLAGS="$LIB_FLAGS $ERLANG_FLAGS $JS_FLAGS -DXP_UNIX $FLAGS"
-CPPFLAGS="$FLAGS $CPPFLAGS"
-# manually linking libm is requred for FreeBSD 7.0
-LDFLAGS="$FLAGS -lm $LDFLAGS"
+
+case "$(uname -s)" in
+  CYGWIN*)
+    FLAGS="$LIB_FLAGS $ERLANG_FLAGS $JS_FLAGS -DXP_WIN $FLAGS"
+    CPPFLAGS="$FLAGS $CPPFLAGS"
+    LDFLAGS="$FLAGS $LDFLAGS"
+    IS_WINDOWS="TRUE"
+    # The erlang cc.sh/ld.sh scripts will convert a -O option
+    # into the same optimization flags erlang itself uses.
+    CFLAGS="-O2"
+    LTCFLAGS="$CFLAGS"
+    ;;
+  *)
+    # XP_UNIX required for jsapi.h and has been tested to work on Linux and Darwin.
+    FLAGS="$LIB_FLAGS $ERLANG_FLAGS $JS_FLAGS -DXP_UNIX $FLAGS"
+    CPPFLAGS="$FLAGS $CPPFLAGS"
+    # manually linking libm is requred for FreeBSD 7.0
+    LDFLAGS="$FLAGS -lm $LDFLAGS"
+    ;;
+esac
+
+AM_CONDITIONAL([WINDOWS], [test x$IS_WINDOWS = xTRUE])
 
 AC_CHECK_LIB([mozjs], [JS_NewContext], [], [
     AC_CHECK_LIB([js], [JS_NewContext], [], [
-        AC_MSG_ERROR([Could not find the js library.
+        AC_CHECK_LIB([js3250], [JS_NewContext], [], [
+            AC_CHECK_LIB([js32], [JS_NewContext], [], [
+                AC_MSG_ERROR([Could not find the js library.
 
-Is the Mozilla SpiderMonkey library installed?])])])
+Is the Mozilla SpiderMonkey library installed?])])])])])
 
 AC_CHECK_HEADER([jsapi.h], [], [
     AC_CHECK_HEADER([js/jsapi.h],
@@ -116,18 +135,39 @@
 CFLAGS="$OLD_CFLAGS"
 AC_LANG_POP(C)
 
-AC_CHECK_ICU([3])
+AC_ARG_WITH([win32-icu-binaries], [AC_HELP_STRING([--with-win32-icu-binaries=PATH],
+    [set PATH to the Win32 native ICU binaries directory])], [
+    ICU_CONFIG="" # supposed to be a command to query options...
+    ICU_LOCAL_CFLAGS="-I$withval/include"
+    ICU_LOCAL_LDFLAGS="-L$withval/lib"
+    ICU_LOCAL_BIN=$withval/bin
+], [
+    AC_CHECK_ICU([3])
+    ICU_LOCAL_CFLAGS=`$ICU_CONFIG --cppflags-searchpath`
+    ICU_LOCAL_LDFLAGS=`$ICU_CONFIG --ldflags-searchpath`
+    ICU_LOCAL_BIN=
+])
 
-ICU_LOCAL_CFLAGS=`$ICU_CONFIG --cppflags-searchpath`
-ICU_LOCAL_LDFLAGS=`$ICU_CONFIG --ldflags-searchpath`
 
 AC_SUBST(ICU_CONFIG)
 AC_SUBST(ICU_LOCAL_CFLAGS)
 AC_SUBST(ICU_LOCAL_LDFLAGS)
+AC_SUBST(ICU_LOCAL_BIN)
+
+AC_ARG_WITH([win32-curl], [AC_HELP_STRING([--with-win32-curl=PATH],
+    [set PATH to the Win32 native curl directory])], [
+    # default build on windows is a static lib, and that's what we want too
+    CURL_CFLAGS="-I$withval/include -DCURL_STATICLIB"
+    CURL_LIBS="$withval/lib/libcurl"
+    CURL_LDFLAGS="-l$CURL_LIBS -lWs2_32 -lkernel32 -luser32 -ladvapi32 -lWldap32"
+], [
+    AC_CHECK_CURL([7.15.5])
+    CURL_LDFLAGS=-lcurl
+])
 
-AC_CHECK_CURL([7.15.5])
 AC_SUBST(CURL_CFLAGS)
 AC_SUBST(CURL_LIBS)
+AC_SUBST(CURL_LDFLAGS)
 
 case "$(uname -s)" in
   Linux)
@@ -268,8 +308,15 @@
 AC_SUBST([localstatelibdir], [${localstatedir}/lib/${package_identifier}])
 AC_SUBST([localstatelogdir], [${localstatedir}/log/${package_identifier}])
 AC_SUBST([localstaterundir], [${localstatedir}/run/${package_identifier}])
-AC_SUBST([locallibbindir], [${locallibdir}/bin])
-AC_SUBST([localerlanglibdir], [${locallibdir}/erlang/lib])
+
+# On Windows we install directly into our erlang distribution.
+if test x${IS_WINDOWS} = xTRUE; then
+    AC_SUBST([locallibbindir], [${prefix}/bin])
+    AC_SUBST([localerlanglibdir], [${libdir}])
+else
+    AC_SUBST([locallibbindir], [${locallibdir}/bin])
+    AC_SUBST([localerlanglibdir], [${locallibdir}/erlang/lib])
+fi
 
 # fix for older autotools that don't define "abs_top_YYY" by default
 AC_SUBST(abs_top_srcdir)
@@ -280,6 +327,7 @@
 AC_CONFIG_FILES([Makefile])
 AC_CONFIG_FILES([bin/couchjs.tpl])
 AC_CONFIG_FILES([bin/couchdb.tpl])
+AC_CONFIG_FILES([bin/couchdb.bat.tpl])
 AC_CONFIG_FILES([bin/Makefile])
 AC_CONFIG_FILES([etc/couchdb/Makefile])
 AC_CONFIG_FILES([etc/couchdb/default.ini.tpl])
@@ -304,6 +352,21 @@
 
 AC_OUTPUT
 
+# *sob* - on Windows libtool fails as 'libname_spec' isn't correct (it
+# expects GNU style lib names).  I can't work out how to configure this
+# option sanely, so we pass the script through sed to modify it.
+# Also, the erlang cc.sh script doesn't cope well with the '-link' command
+# line option libtool provides.
+# PLEASE, someone help put this out of its misery!!
+# This hackery is being tracked via COUCHDB-440.
+if test x${IS_WINDOWS} = xTRUE; then
+    sed -e 's,libname_spec="lib\\$name",libname_spec="\\\$name",' \
+        -e 's,-link,,' \
+        < libtool > libtool.tmp
+    mv libtool.tmp libtool
+    # probably would chmod +x if we weren't on windows...
+fi
+
 echo
 echo "You have configured Apache CouchDB, time to relax."
 echo

Modified: couchdb/trunk/etc/couchdb/Makefile.am
URL: http://svn.apache.org/viewvc/couchdb/trunk/etc/couchdb/Makefile.am?rev=805243&r1=805242&r2=805243&view=diff
==============================================================================
--- couchdb/trunk/etc/couchdb/Makefile.am (original)
+++ couchdb/trunk/etc/couchdb/Makefile.am Tue Aug 18 01:27:03 2009
@@ -24,6 +24,17 @@
 couchjs_command_name = `echo couchjs | sed '$(transform)'`
 couchjs_dev_command_name = `echo couchjs_dev | sed '$(transform)'`
 
+if WINDOWS
+default.ini: default.ini.tpl
+	sed -e "s|%bindir%|.|g" \
+	    -e "s|%localconfdir%|$(localconfdir)|g" \
+	    -e "s|%localdatadir%|../share/couchdb|g" \
+	    -e "s|%localstatelibdir%|../var/lib/couchdb|g" \
+	    -e "s|%localstatelogdir%|../var/log/couchdb|g" \
+	    -e "s|%couchprivlibdir%|../lib/couch-$(version)/priv/lib|g" \
+	    -e "s|%couchjs_command_name%|couchjs.exe|g" \
+	< $< > $@
+else
 default.ini: default.ini.tpl
 	sed -e "s|%bindir%|$(bindir)|g" \
 	    -e "s|%localconfdir%|$(localconfdir)|g" \
@@ -33,6 +44,7 @@
 	    -e "s|%couchprivlibdir%|$(couchprivlibdir)|g" \
 	    -e "s|%couchjs_command_name%|$(couchjs_command_name)|g" \
 	< $< > $@
+endif
 
 default_dev.ini: default.ini.tpl
 	sed -e "s|%bindir%|$(abs_top_srcdir)/bin|g" \
@@ -48,16 +60,16 @@
 	cp local.ini $@
 
 install-data-hook:
-	if test ! -f "$(DESTDIR)/$(localconfdir)/local.ini"; then \
-	    cp $(srcdir)/local.ini "$(DESTDIR)/$(localconfdir)/local.ini"; \
+	if test ! -f "$(DESTDIR)$(localconfdir)/local.ini"; then \
+	    cp $(srcdir)/local.ini "$(DESTDIR)$(localconfdir)/local.ini"; \
 	fi
 	if test ! "$(mkdir_p)" = ""; then \
-	    $(mkdir_p) "$(DESTDIR)/$(localconfdir)/default.d"; \
-	    $(mkdir_p) "$(DESTDIR)/$(localconfdir)/local.d"; \
+	    $(mkdir_p) "$(DESTDIR)$(localconfdir)/default.d"; \
+	    $(mkdir_p) "$(DESTDIR)$(localconfdir)/local.d"; \
 	else \
 	    echo "WARNING: You may have to create these directories by hand."; \
-	    mkdir -p "$(DESTDIR)/$(localconfdir)/default.d"; \
-	    mkdir -p "$(DESTDIR)/$(localconfdir)/local.d"; \
+	    mkdir -p "$(DESTDIR)$(localconfdir)/default.d"; \
+	    mkdir -p "$(DESTDIR)$(localconfdir)/local.d"; \
 	fi
 
 uninstall-local:

Modified: couchdb/trunk/src/couchdb/Makefile.am
URL: http://svn.apache.org/viewvc/couchdb/trunk/src/couchdb/Makefile.am?rev=805243&r1=805242&r2=805243&view=diff
==============================================================================
--- couchdb/trunk/src/couchdb/Makefile.am (original)
+++ couchdb/trunk/src/couchdb/Makefile.am Tue Aug 18 01:27:03 2009
@@ -13,6 +13,11 @@
 SUBDIRS = priv
 
 ICU_LOCAL_FLAGS = $(ICU_LOCAL_CFLAGS) $(ICU_LOCAL_LDFLAGS)
+if WINDOWS
+ICU_LOCAL_LIBS=-licuuc -licudt -licuin
+else
+ICU_LOCAL_LIBS=-licuuc -licudata -licui18n
+endif
 
 # devdocdir = $(localdocdir)/developer/couchdb
 couchlibdir = $(localerlanglibdir)/couch-$(version)
@@ -25,19 +30,28 @@
 couch_erl_driver_la_SOURCES = couch_erl_driver.c
 couch_erl_driver_la_LDFLAGS = -module -avoid-version $(ICU_LOCAL_FLAGS)
 couch_erl_driver_la_CFLAGS = $(ICU_LOCAL_FLAGS)
-couch_erl_driver_la_LIBADD = -licuuc -licudata -licui18n
+couch_erl_driver_la_LIBADD = $(ICU_LOCAL_LIBS)
 
 locallibbin_PROGRAMS = couchjs
 couchjs_SOURCES = couch_js.c curlhelper.c curlhelper.h
-couchjs_LDLAGS = $(CURL_LDLAGS)
+couchjs_LDFLAGS = $(CURL_LDFLAGS)
 couchjs_CFLAGS = $(CURL_CFLAGS)
-couchjs_LDADD = -lcurl
+couchjs_LDADD = $(CURL_LDFLAGS)
+
+if WINDOWS
+priv_couchspawnkillable_win_SOURCES = priv/couchspawnkillable_win.c
+couchpriv_PROGRAMS = priv/couchspawnkillable_win
+couch_erl_driver_la_LDFLAGS += -no-undefined
+
+# copy ICU dlls for the erlang driver
+dist_couch_erl_driver_la_DATA=$(ICU_LOCAL_BIN)/icuuc42.dll $(ICU_LOCAL_BIN)/icudt42.dll $(ICU_LOCAL_BIN)/icuin42.dll
+couch_erl_driver_ladir=$(bindir)
+endif
 
 couchinclude_DATA = couch_db.hrl
 
 couchebin_DATA = $(compiled_files)
 
-couchpriv_SCRIPTS = priv/couchspawnkillable
 
 # dist_devdoc_DATA = $(doc_base) $(doc_modules)
 
@@ -98,6 +112,7 @@
 EXTRA_DIST = $(source_files) couch_db.hrl couch_stats.hrl
 
 compiled_files = \
+	priv/couchspawnkillable \
     couch.app \
     couch_btree.beam \
     couch_batch_save.beam \
@@ -191,14 +206,31 @@
 %.beam: %.erl couch_db.hrl
 	$(ERLC) $(ERLC_FLAGS) ${TEST} $<;
 
+if WINDOWS
+priv/couchspawnkillable: priv/couchspawnkillable_win
+	cp $< $@
+else
+priv/couchspawnkillable: priv/couchspawnkillable.sh
+	cp $< $@
+endif
+
 install-data-hook:
-	if test -f "$(DESTDIR)/$(couchprivlibdir)/couch_erl_driver"; then \
-	    rm -f "$(DESTDIR)/$(couchprivlibdir)/couch_erl_driver.so"; \
-	    cd "$(DESTDIR)/$(couchprivlibdir)" && \
+	if test -f "$(DESTDIR)$(couchprivlibdir)/couch_erl_driver"; then \
+	    rm -f "$(DESTDIR)$(couchprivlibdir)/couch_erl_driver.so"; \
+	    cd "$(DESTDIR)$(couchprivlibdir)" && \
 	        $(LN_S) couch_erl_driver couch_erl_driver.so; \
 	fi
+if WINDOWS
+# libtool and automake have defeated markh.  For each of our executables
+# we end up with 2 copies - one directly in the 'target' folder (eg, 'priv')
+# and another - the correct one - in .libs.  The former doesn't work but is 
+# what gets installed for 'couchspawnkillable' - but the correct one for
+# couchjs.exe *does* get copied.  *shrug*  So just clobber it with the 
+# correct one here... See bug COUCHDB-439
+	$(INSTALL) priv/.libs/couchspawnkillable_win.exe "$(DESTDIR)$(couchprivdir)/couchspawnkillable.exe"
+endif
 
 uninstall-local:
-	if test -f "$(DESTDIR)/$(couchprivlibdir)/couch_erl_driver"; then \
-	    rm -f "$(DESTDIR)/$(couchprivlibdir)/couch_erl_driver.so"; \
+	if test -f "$(DESTDIR)$(couchprivlibdir)/couch_erl_driver"; then \
+	    rm -f "$(DESTDIR)$(couchprivlibdir)/couch_erl_driver.so"; \
 	fi

Added: couchdb/trunk/src/couchdb/priv/couchspawnkillable_win.c
URL: http://svn.apache.org/viewvc/couchdb/trunk/src/couchdb/priv/couchspawnkillable_win.c?rev=805243&view=auto
==============================================================================
--- couchdb/trunk/src/couchdb/priv/couchspawnkillable_win.c (added)
+++ couchdb/trunk/src/couchdb/priv/couchspawnkillable_win.c Tue Aug 18 01:27:03 2009
@@ -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;
+}



Mime
View raw message