Details
-
Bug
-
Status: Closed
-
Major
-
Resolution: Won't Fix
-
None
-
None
-
None
Description
CouchDB 1.6.1 does not play nice with Erlang OTP 17.0 on Windows when there are spaces in the installation path. The release notes at this page imply this should work with Erlang OTP 17.0.
Error
X: CouchError: {{badmatch, {error, {enoent, [{erlang,open_port, [{spawn, "c:/Program Files (x86)/Apache Software Foundation/CouchDB/lib/couch-1.6.1/priv/couchspawnkillable ./couchjs.exe ../share/couchdb/server/main.js"}, [stream,{line,4096},binary,exit_status,hide]], []}, {couch_os_process,init,1, [{file, "c:/cygwin/relax/APACHE~2.1/src/couchdb/couch_os_process.erl"}, {line,148}]}, {gen_server,init_it,6,[{file,"gen_server.erl"},{line,306}]}, {proc_lib,init_p_do_apply,3, [{file,"proc_lib.erl"},{line,239}]}]}}}, [{couch_query_servers,new_process,3, [{file,"c:/cygwin/relax/APACHE~2.1/src/couchdb/couch_query_servers.erl"}, {line,477}]}, {couch_query_servers,lang_proc,3, [{file,"c:/cygwin/relax/APACHE~2.1/src/couchdb/couch_query_servers.erl"}, {line,462}]}, {couch_query_servers,handle_call,3, [{file,"c:/cygwin/relax/APACHE~2.1/src/couchdb/couch_query_servers.erl"}, {line,334}]}, {gen_server,handle_msg,5,[{file,"gen_server.erl"},{line,580}]}, {proc_lib,init_p_do_apply,3,[{file,"proc_lib.erl"},{line,239}]}]}
Analysis
I traced the problem to this block of code:
init([Command, Options, PortOptions]) -> PrivDir = couch_util:priv_dir(), Spawnkiller = filename:join(PrivDir, "couchspawnkillable"), BaseProc = #os_proc{ command=Command, port=open_port({spawn, Spawnkiller ++ " " ++ Command}, PortOptions), writer=fun writejson/2, reader=fun readjson/1 },
The reason it fails with OTP 17.0 is because code:priv_dir(couch) returns a different value than Erlang 16B02 (code:priv_dir(couch) is called by couch_util:priv_dir()). See differences below:
2> code:priv_dir(couch).
"c:/PROGRA~2/APACHE~1/CouchDB2/lib/couch-1.6.1/priv"
2> code:priv_dir(couch).
"c:/Program Files (x86)/Apache Software Foundation/CouchDB/lib/couch-1.6.1/priv"
So when open_port is called in OTP 17.0, it is passed a command that looks something like:
"C:/Program Files (x86)/Apache Software Foundation/CouchDb/lib/couch-1.6.1/priv/couchspawnkillable.exe ./couchjs.exe ../share/couchdb/server/main.js"
In Erlang 16B02 something like:
"c:/PROGRA~2/APACHE~1/CouchDB2/lib/couch-1.6.1/priv/couchspawnkillable.exe ./couchjs.exe ../share/couchdb/server/main.js"
Basically, open_port is splitting the command up by spaces and assuming that the C:/Program part is the command it should be executing. Obviously, this doesn't exist and so open_port fails.
Possible Solution
Wrap the Spawnkill part in escaped quotes. open_port was fixed a long time to handle this (see erlang release notes, OTP-8055).
I changed the init fun to this, compiled on Ubuntu, and tested on Windows. This solved my problem.
init([Command, Options, PortOptions]) -> PrivDir = couch_util:priv_dir(), Spawnkiller = filename:join(PrivDir, "couchspawnkillable"), BaseProc = #os_proc{ command=Command, port=open_port({spawn, Spawnkiller ++ " " ++ Command}, PortOptions), writer=fun writejson/2, reader=fun readjson/1 },