From patchwork Fri Oct 17 15:39:00 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: cmdserver: add command to get pid of server handling current connection From: Yuya Nishihara X-Patchwork-Id: 6369 Message-Id: <1b432767e0829aba65a8.1413560340@mimosa> To: mercurial-devel@selenic.com Date: Sat, 18 Oct 2014 00:39:00 +0900 # HG changeset patch # User Yuya Nishihara # Date 1413556690 -32400 # Fri Oct 17 23:38:10 2014 +0900 # Node ID 1b432767e0829aba65a8f63bdcdb3bb9cabbce4f # Parent 840be5ca03e1db16ba994e55597771c418166c97 cmdserver: add command to get pid of server handling current connection Since unix-mode server forks child process per request, client cannot know the pid of the server, which is necessary to send SIGINT for example. Though Linux has getsockopt(SO_PEERCRED), it cannot be used because the server fork()s after accept(). So commandserver should provide "getpid" command. diff --git a/mercurial/commandserver.py b/mercurial/commandserver.py --- a/mercurial/commandserver.py +++ b/mercurial/commandserver.py @@ -212,6 +212,9 @@ class server(object): """ writes the current encoding to the result channel """ self.cresult.write(encoding.encoding) + def getpid(self): + self.cresult.write(struct.pack('>i', os.getpid())) + def serveone(self): cmd = self.client.readline()[:-1] if cmd: @@ -226,7 +229,8 @@ class server(object): return cmd != '' capabilities = {'runcommand' : runcommand, - 'getencoding' : getencoding} + 'getencoding' : getencoding, + 'getpid' : getpid} def serve(self): hellomsg = 'capabilities: ' + ' '.join(sorted(self.capabilities)) diff --git a/tests/test-commandserver.t b/tests/test-commandserver.t --- a/tests/test-commandserver.t +++ b/tests/test-commandserver.t @@ -16,7 +16,7 @@ ... # run an arbitrary command to make sure the next thing the server ... # sends isn't part of the hello message ... runcommand(server, ['id']) - o, 'capabilities: getencoding runcommand\nencoding: *' (glob) + o, 'capabilities: getencoding getpid runcommand\nencoding: *' (glob) *** runcommand id 000000000000 tip @@ -519,6 +519,21 @@ check that local configs for the cached prompt: 5678 +get pid of the server (same as subprocess' in pipe mode): + + >>> import struct + >>> from hgclient import readchannel, check + >>> @check + ... def getpid(server): + ... readchannel(server) + ... server.stdin.write('getpid\n') + ... ch, data = readchannel(server) + ... print '%c, %r' % (ch, data) + ... pid, = struct.unpack('>i', data) + ... assert pid == server.pid + r, '*' (glob) + + start without repository: $ cd .. @@ -531,7 +546,7 @@ start without repository: ... # run an arbitrary command to make sure the next thing the server ... # sends isn't part of the hello message ... runcommand(server, ['id']) - o, 'capabilities: getencoding runcommand\nencoding: *' (glob) + o, 'capabilities: getencoding getpid runcommand\nencoding: *' (glob) *** runcommand id abort: there is no Mercurial repository here (.hg not found) [255] @@ -562,7 +577,7 @@ unix domain socket: ... print '%c, %r' % (ch, data) ... runcommand(conn, ['id']) >>> check(hellomessage, server.connect) - o, 'capabilities: getencoding runcommand\nencoding: *' (glob) + o, 'capabilities: getencoding getpid runcommand\nencoding: *' (glob) *** runcommand id eff892de26ec tip bm1/bm2/bm3 >>> def unknowncommand(conn):