# # patch "ChangeLog" # from [3c7f71137a4c3af460295b48b0c0ccca3bca2ffd] # to [f42ed6126e6a9e97ed93ffdf3c2ba001960ab902] # # patch "app_state.cc" # from [da30ae47064dd3743fd31e7ce99dcb9c7fdf7813] # to [a97a7bf9127e66d1d8e7d0577cad1ed86a0dc42f] # # patch "app_state.hh" # from [27b58d6683bc026b41c07308738952067bf82926] # to [a5ac3a99f998fee5a71b4f6201e6d26b086c7589] # # patch "commands.cc" # from [dcc5c1e01f50623e13f34fffd221f6eeaefbb42a] # to [dffdd24d07b1048fa1e02fab7353926776987720] # # patch "configure.ac" # from [91aa8dc3693ec6a89a6fb6c0a3e9f987d493d1e4] # to [184cb4ceea71542da6bb7ae96548a3efbb8a4a6d] # # patch "lua.cc" # from [42373a056c2983c5f3d6303eb33c8c8ed88b2aae] # to [6d767a93a1f123c5ee86f3e1dd352da1beecbbf9] # # patch "monotone.cc" # from [7001aaae35d22a6d78dbda8638d3635ca8d1081e] # to [bdcc7b74c7406ae184eb45958ee49ef02980e4fd] # # patch "monotone.texi" # from [2e63f434deec3b8378969cc7d63cda1c225f9d42] # to [24da1d645f7fd93432c75fc244657f26501077fe] # # patch "options.hh" # from [0b886b3cfe2da40ca5e217f15c59d6593dd1de11] # to [de2a21d88f641eeb889184d57af3c433b91556ec] # # patch "platform.hh" # from [1f01b1dee6b2c96235160d63197f92f740790f8d] # to [5f5c469fcbb9f1748ed15af94855a4402b95f0c2] # # patch "tests/t_netsync_sigpipe.at" # from [87b55c8ec8fb09e514b35368e851c477c726bdaa] # to [773f9ac6d0592673c109f68618bcdbf0ff5a17f9] # # patch "tests/t_netsync_single.at" # from [faa5253849ae86d140b67fb93609d191456b0ec3] # to [d7b40fcf0529e589e987774f569edeae0889257f] # # patch "testsuite.at" # from [a62d0f8215b1359408ce4621cbd50bae9a9c1c94] # to [c367205bf28bd3358c49e3525815e48b134316fb] # # patch "unix/process.cc" # from [3dfbca0b6549d1b91d19960ed704d6e4ed8ea042] # to [0cfa3c05d2dc345fedae7351557b46a502d14c05] # # patch "win32/process.cc" # from [8290190317b7b74e281eaa749b50393c32928928] # to [a7d8affe8f0801f5220771f1022285936d48d1f7] # --- ChangeLog +++ ChangeLog @@ -1,5 +1,25 @@ 2005-05-05 Matthew Gregan + * monotone.texi: Document --pid-file option for serve command. + * app_state.{cc,hh} (set_pidfile, pidfile): New function, new + member. + * commands.cc (pid_file): New class. + (CMD(serve)): Use pid_file. + * monotone.cc (coptions, cppmain): Add command-specific option + --pid-file. + * options.hh (OPT_PIDFILE): New option. + * {unix,win32}/process.cc (get_process_id): New function. + (process_{spawn,wait,kill}): Use pid_t. + * platform.hh (process_{spawn,wait,kill}): Use pid_t. + (get_process_id): New function + * configure.ac: Test for pid_t. + * lua.cc (monotone_{spawn,wait,kill}_for_lua): Use pid_t. + * testsuite.at: Update netsync kill functions to use pid file. + * tests/t_netsync_sigpipe.at: Update to use pid file. + * tests/t_netsync_single.at: Update to use pid file. + +2005-05-05 Matthew Gregan + * work.cc: Use attr_file_name rather than hardcoded strings. 2005-05-04 Brian Campbell --- app_state.cc +++ app_state.cc @@ -294,6 +294,12 @@ } void +app_state::set_pidfile(utf8 const & p) +{ + pidfile = mkpath(p()); +} + +void app_state::add_revision(utf8 const & selector) { revision_selectors.push_back(selector); --- app_state.hh +++ app_state.hh @@ -42,6 +42,7 @@ file_path relative_directory; bool found_working_copy; long depth; + fs::path pidfile; void allow_working_copy(); void require_working_copy(); @@ -67,6 +68,7 @@ void set_date(utf8 const & date); void set_author(utf8 const & author); void set_depth(long depth); + void set_pidfile(utf8 const & pidfile); void add_revision(utf8 const & selector); void set_stdhooks(bool b); --- commands.cc +++ commands.cc @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -275,6 +276,37 @@ process(app, string(#realcommand), args); \ } +struct pid_file +{ + explicit pid_file(fs::path const & p) + : path(p) + { + if (path == "") + return; + N(!fs::exists(path), F("pid file '%s' already exists") % path.string()); + file.open(path); + file << get_process_id(); + file.flush(); + P(F("pid file '%s' created for pid '%d'") % path.string() % get_process_id()); + } + + ~pid_file() + { + if (path == "") + return; + pid_t pid; + fs::ifstream(path) >> pid; + if (pid == get_process_id()) { + file.close(); + fs::remove(path); + } + } + +private: + fs::ofstream file; + fs::path path; +}; + static void maybe_update_inodeprints(app_state & app) { @@ -1989,11 +2021,13 @@ } CMD(serve, "network", "ADDRESS[:PORTNUMBER] COLLECTION...", - "listen on ADDRESS and serve COLLECTION to connecting clients", OPT_NONE) + "listen on ADDRESS and serve COLLECTION to connecting clients", OPT_PIDFILE) { if (args.size() < 2) throw usage(name); + pid_file pid(app.pidfile); + rsa_keypair_id key; N(guess_default_key(key, app), F("could not guess default signing key")); app.signing_key = key; --- configure.ac +++ configure.ac @@ -378,11 +378,26 @@ ac_cv_type_socklen_t=no) ]) if test $ac_cv_type_socklen_t = yes; then - AC_DEFINE(HAVE_SOCKLEN_T, 1, [Define if platform has real socklen_t.]) + AC_DEFINE(HAVE_SOCKLEN_T, 1, [Define if platform has socklen_t.]) fi ]) TYPE_SOCKLEN_T +AC_DEFUN([TYPE_PID_T], +[AC_CACHE_CHECK([for pid_t], ac_vs_type_pid_t, +[ + AC_TRY_COMPILE( + [#include ], + [pid_t pid = 42; return 0;], + ac_cv_type_pid_t=yes, + ac_cv_type_pid_t=no) +]) + if test $ac_cv_type_socklen_t = no; then + AC_DEFINE(pid_t, unsigned long, [pid_t substitute.]) + fi +]) +TYPE_PID_T + # Checks for library functions. AC_PROG_GCC_TRADITIONAL AC_FUNC_STAT --- lua.cc +++ lua.cc @@ -110,7 +110,8 @@ int n = lua_gettop(L); const char *path = lua_tostring(L, -n); char **argv = (char**)malloc((n+1)*sizeof(char*)); - int ret, i; + int i; + pid_t ret; if (argv==NULL) return 0; argv[0] = (char*)path; @@ -125,7 +126,7 @@ static int monotone_wait_for_lua(lua_State *L) { - int pid = (int)lua_tonumber(L, -1); + pid_t pid = (pid_t)lua_tonumber(L, -1); int res; int ret; ret = process_wait(pid, &res); @@ -138,7 +139,7 @@ monotone_kill_for_lua(lua_State *L) { int n = lua_gettop(L); - int pid = (int)lua_tonumber(L, -2); + pid_t pid = (pid_t)lua_tonumber(L, -2); int sig; if (n>1) sig = (int)lua_tonumber(L, -1); --- monotone.cc +++ monotone.cc @@ -47,6 +47,7 @@ {"date", 0, POPT_ARG_STRING, &argstr, OPT_DATE, "override date/time for commit", NULL}, {"author", 0, POPT_ARG_STRING, &argstr, OPT_AUTHOR, "override author for commit", NULL}, {"depth", 0, POPT_ARG_LONG, &arglong, OPT_DEPTH, "limit the log output to the given number of entries", NULL}, + {"pid-file", 0, POPT_ARG_STRING, &argstr, OPT_PIDFILE, "record process id of server", NULL}, { NULL, 0, 0, NULL, 0, NULL, NULL } }; @@ -348,6 +349,10 @@ app.set_depth(arglong); break; + case OPT_PIDFILE: + app.set_pidfile(string(argstr)); + break; + case OPT_ARGFILE: my_poptStuffArgFile(ctx(), utf8(string(argstr))); break; --- monotone.texi +++ monotone.texi @@ -3610,6 +3610,11 @@ these will clear your defaults, and cause them to be reset to the next person you netsync with. +If a option @option{--pid-file} is specified, the command address@hidden will create the specified file and record the process +identifier of the server in the file. This file can then be read to +identify specific monotone server processes. + @end ftable --- options.hh +++ options.hh @@ -28,4 +28,4 @@ #define OPT_DATE 19 #define OPT_AUTHOR 20 #define OPT_ALL_FILES 21 +#define OPT_PIDFILE 22 - --- platform.hh +++ platform.hh @@ -12,6 +12,7 @@ #include #include "vocab.hh" +#include "config.h" void read_password(std::string const & prompt, char * buf, size_t bufsz); void get_system_flavour(std::string & ident); @@ -20,9 +21,9 @@ // For LUA int existsonpath(const char *exe); int make_executable(const char *path); -int process_spawn(const char * const argv[]); -int process_wait(int pid, int *res); -int process_kill(int pid, int signal); +pid_t process_spawn(const char * const argv[]); +int process_wait(pid_t pid, int *res); +int process_kill(pid_t pid, int signal); int process_sleep(unsigned int seconds); // for term selection @@ -42,4 +43,7 @@ // changed. bool inodeprint_file(file_path const & file, hexenc & ip); +// for netsync 'serve' pidfile support +pid_t get_process_id(); + #endif // __PLATFORM_HH__ --- tests/t_netsync_sigpipe.at +++ tests/t_netsync_sigpipe.at @@ -5,13 +5,9 @@ m4_define([NETSYNC_KILLPIPE], [ if test "$OSTYPE" == "msys"; then - #ps |awk -- '{p=$NF;a=1;if(p=="COMMAND")next;pp=split(p,ps,"/");if(ps[[pp]]=="monotone")system("kill -PIPE " $a);}' - # If we really wanted to do this on Windows, the above is correct. But - # there is no SIGPIPE on Windows and hence we don't really need to test this - # behaviour there. Hence, we just do nothing. echo "No SIGPIPE on MinGW" else - killall -PIPE monotone 2>/dev/null + kill -PIPE `cat monotone_at.pid` 2>/dev/null fi ]) --- tests/t_netsync_single.at +++ tests/t_netsync_single.at @@ -24,7 +24,7 @@ VER0=`BASE_REVISION` NETSYNC_KILLHARD - MONOTONE --rcfile=netsync.lua serve 127.0.0.1:$_PORT testbranch & + MONOTONE --rcfile=netsync.lua --pid-file=monotone_at.pid serve 127.0.0.1:$_PORT testbranch & sleep 5 AT_CHECK(MONOTONE --rcfile=netsync.lua --db=test2.db pull 127.0.0.1:$_PORT testbranch, [], [ignore], [ignore]) NETSYNC_KILLHARD --- testsuite.at +++ testsuite.at @@ -334,32 +334,25 @@ m4_define([MONOTONE3], MONOTONE --db=test3.db) m4_define([NETSYNC_KILL], [ -if test "$OSTYPE" == "msys"; then - ps |awk -- '{p=$NF;a=1;if(p=="COMMAND")next;pp=split(p,ps,"/");if(ps[[pp]]=="monotone")system("kill " $a);}' - # MinGW has no killall. The weird a=1 thing is to avoid autotest treating $1 as its own parameter -else - killall monotone 2>/dev/null -fi + kill `cat monotone_at.pid` 2>/dev/null + rm -f monotone_at.pid 2>/dev/null ]) m4_define([NETSYNC_KILLHARD], [ -if test "$OSTYPE" == "msys"; then - ps |awk -- '{p=$NF;a=1;if(p=="COMMAND")next;pp=split(p,ps,"/");if(ps[[pp]]=="monotone")system("kill -KILL " $a);}' -else - killall -KILL monotone 2>/dev/null -fi + kill -KILL `cat monotone_at.pid` 2>/dev/null + rm -f monotone_at.pid 2>/dev/null ]) # run as NETSYNC_SERVE_N_START(2|3, collection name) # note that NETSYNC_SERVE_START is _not_ a special case of this macro. m4_define([NETSYNC_SERVE_N_START], [ NETSYNC_KILLHARD -MONOTONE --db=test$1.db --rcfile=netsync.lua serve localhost:$_PORT $2 & +MONOTONE --db=test$1.db --rcfile=netsync.lua --pid-file=monotone_at.pid serve localhost:$_PORT $2 & sleep 4 ]) # run as NETSYNC_SERVE_START(collection name) m4_define([NETSYNC_SERVE_START], [ NETSYNC_KILLHARD -MONOTONE --rcfile=netsync.lua serve localhost:$_PORT $1 & +MONOTONE --rcfile=netsync.lua --pid-file=monotone_at.pid serve localhost:$_PORT $1 & sleep 4 ]) # run as NETSYNC_SERVE_STOP --- unix/process.cc +++ unix/process.cc @@ -50,7 +50,7 @@ return chmod(path, mode); } -int process_spawn(const char * const argv[]) +pid_t process_spawn(const char * const argv[]) { { std::ostringstream cmdline_ss; @@ -72,14 +72,14 @@ execvp(argv[0], (char * const *)argv); return -1; default: /* Parent */ - return (int)pid; + return pid; } } -int process_wait(int pid, int *res) +int process_wait(pid_t pid, int *res) { int status; - pid = waitpid((pid_t)pid, &status, 0); + pid = waitpid(pid, &status, 0); if (WIFEXITED(status)) *res = WEXITSTATUS(status); else @@ -87,12 +87,17 @@ return 0; } -int process_kill(int pid, int signal) +int process_kill(pid_t pid, int signal) { - return kill((pid_t)pid, signal); + return kill(pid, signal); } int process_sleep(unsigned int seconds) { return sleep(seconds); } + +pid_t get_process_id() +{ + return getpid(); +} --- win32/process.cc +++ win32/process.cc @@ -27,7 +27,7 @@ return 0; /* Basically meaningless on win32 */ } -int process_spawn(const char * const argv[]) +pid_t process_spawn(const char * const argv[]) { int i; char *realexe,*filepart; @@ -88,10 +88,10 @@ } free(realexe); CloseHandle(pi.hThread); - return (int)pi.hProcess; + return pi.hProcess; } -int process_wait(int pid, int *res) +pid_t process_wait(pid_t pid, int *res) { HANDLE hProcess = (HANDLE)pid; if (WaitForSingleObject(hProcess, INFINITE)==WAIT_FAILED) @@ -105,7 +105,7 @@ return 0; } -int process_kill(int pid, int signal) +int process_kill(pid_t pid, int signal) { HANDLE hProcess = (HANDLE)pid; if (TerminateProcess(hProcess, 1)==0) @@ -118,3 +118,9 @@ Sleep(seconds*1000); return 0; } + +pid_t get_process_id() +{ + return GetCurrentProcessId(); +} +