diff options
Diffstat (limited to 'apps/couch/src/couch_os_process.erl')
-rw-r--r-- | apps/couch/src/couch_os_process.erl | 37 |
1 files changed, 24 insertions, 13 deletions
diff --git a/apps/couch/src/couch_os_process.erl b/apps/couch/src/couch_os_process.erl index 2a6d92a7..0c6f284f 100644 --- a/apps/couch/src/couch_os_process.erl +++ b/apps/couch/src/couch_os_process.erl @@ -27,7 +27,8 @@ port, writer, reader, - timeout=5000 + timeout=5000, + idle }). start_link(Command) -> @@ -104,12 +105,15 @@ readjson(#os_proc{} = OsProc) -> % gen_server API init([Command, Options, PortOptions]) -> + V = couch_config:get("query_server_config", "os_process_idle_limit", "300"), + IdleLimit = list_to_integer(V) * 1000, Spawnkiller = filename:join([code:priv_dir(couch), "couchspawnkillable.sh"]), BaseProc = #os_proc{ command=Command, port=open_port({spawn, Spawnkiller ++ " " ++ Command}, PortOptions), writer=fun writejson/2, - reader=fun readjson/1 + reader=fun readjson/1, + idle=IdleLimit }, KillCmd = readline(BaseProc), Pid = self(), @@ -131,32 +135,32 @@ init([Command, Options, PortOptions]) -> Proc#os_proc{timeout=TimeOut} end end, BaseProc, Options), - {ok, OsProc}. + {ok, OsProc, IdleLimit}. terminate(_Reason, #os_proc{port=Port}) -> catch port_close(Port), ok. -handle_call({set_timeout, TimeOut}, _From, OsProc) -> - {reply, ok, OsProc#os_proc{timeout=TimeOut}}; -handle_call({prompt, Data}, _From, OsProc) -> +handle_call({set_timeout, TimeOut}, _From, #os_proc{idle=Idle}=OsProc) -> + {reply, ok, OsProc#os_proc{timeout=TimeOut}, Idle}; +handle_call({prompt, Data}, _From, #os_proc{idle=Idle}=OsProc) -> #os_proc{writer=Writer, reader=Reader} = OsProc, try Writer(OsProc, Data), - {reply, {ok, Reader(OsProc)}, OsProc} + {reply, {ok, Reader(OsProc)}, OsProc, Idle} catch throw:{error, OsError} -> - {reply, OsError, OsProc}; + {reply, OsError, OsProc, Idle}; throw:{fatal, OsError} -> {stop, normal, OsError, OsProc}; throw:OtherError -> {stop, normal, OtherError, OsProc} end. -handle_cast({send, Data}, #os_proc{writer=Writer}=OsProc) -> +handle_cast({send, Data}, #os_proc{writer=Writer, idle=Idle}=OsProc) -> try Writer(OsProc, Data), - {noreply, OsProc} + {noreply, OsProc, Idle} catch throw:OsError -> ?LOG_ERROR("Failed sending data: ~p -> ~p", [Data, OsError]), @@ -164,16 +168,23 @@ handle_cast({send, Data}, #os_proc{writer=Writer}=OsProc) -> end; handle_cast(stop, OsProc) -> {stop, normal, OsProc}; -handle_cast(Msg, OsProc) -> +handle_cast(Msg, #os_proc{idle=Idle}=OsProc) -> ?LOG_DEBUG("OS Proc: Unknown cast: ~p", [Msg]), - {noreply, OsProc}. + {noreply, OsProc, Idle}. +handle_info(timeout, #os_proc{idle=Idle}=OsProc) -> + gen_server:cast(couch_proc_manager, {os_proc_idle, self()}), + erlang:garbage_collect(), + {noreply, OsProc, Idle}; handle_info({Port, {exit_status, 0}}, #os_proc{port=Port}=OsProc) -> ?LOG_INFO("OS Process terminated normally", []), {stop, normal, OsProc}; handle_info({Port, {exit_status, Status}}, #os_proc{port=Port}=OsProc) -> ?LOG_ERROR("OS Process died with status: ~p", [Status]), - {stop, {exit_status, Status}, OsProc}. + {stop, {exit_status, Status}, OsProc}; +handle_info(Msg, #os_proc{idle=Idle}=OsProc) -> + ?LOG_DEBUG("OS Proc: Unknown info: ~p", [Msg]), + {noreply, OsProc, Idle}. code_change(_OldVsn, State, _Extra) -> {ok, State}. |