summaryrefslogtreecommitdiffstats
path: root/git_config.py
diff options
context:
space:
mode:
authorDoug Anderson <dianders@google.com>2010-10-27 17:06:01 -0700
committerShawn O. Pearce <sop@google.com>2010-10-29 08:14:56 -0700
commit06d029c1c8c06a6d446b7cc4d5e763ff0754b149 (patch)
tree5d670c3a78fd55db461d99021db13d699c483dcd /git_config.py
parentb715b148076ef589e806a98a183c8f4468f75cf6 (diff)
downloadgit-repo-06d029c1c8c06a6d446b7cc4d5e763ff0754b149.tar.gz
Check for existing SSH ControlMaster
Be more thorough about checking for an existing ssh master by running a test command first, and only opening up a new master if the test fails to connect. Change-Id: I56fe8e7b4dbc123675b7f259e81d359ed0cd55cf Signed-off-by: Shawn O. Pearce <sop@google.com>
Diffstat (limited to 'git_config.py')
-rw-r--r--git_config.py53
1 files changed, 41 insertions, 12 deletions
diff --git a/git_config.py b/git_config.py
index 1382d5db..138470c5 100644
--- a/git_config.py
+++ b/git_config.py
@@ -356,18 +356,21 @@ class RefSpec(object):
356 return s 356 return s
357 357
358 358
359_ssh_cache = {} 359_master_processes = []
360_master_keys = set()
360_ssh_master = True 361_ssh_master = True
361 362
362def _open_ssh(host, port=None): 363def _open_ssh(host, port=None):
363 global _ssh_master 364 global _ssh_master
364 365
366 # Check to see whether we already think that the master is running; if we
367 # think it's already running, return right away.
365 if port is not None: 368 if port is not None:
366 key = '%s:%s' % (host, port) 369 key = '%s:%s' % (host, port)
367 else: 370 else:
368 key = host 371 key = host
369 372
370 if key in _ssh_cache: 373 if key in _master_keys:
371 return True 374 return True
372 375
373 if not _ssh_master \ 376 if not _ssh_master \
@@ -377,15 +380,39 @@ def _open_ssh(host, port=None):
377 # 380 #
378 return False 381 return False
379 382
380 command = ['ssh', 383 # We will make two calls to ssh; this is the common part of both calls.
381 '-o','ControlPath %s' % ssh_sock(), 384 command_base = ['ssh',
382 '-M', 385 '-o','ControlPath %s' % ssh_sock(),
383 '-N', 386 host]
384 host]
385
386 if port is not None: 387 if port is not None:
387 command[3:3] = ['-p',str(port)] 388 command_base[1:1] = ['-p',str(port)]
388 389
390 # Since the key wasn't in _master_keys, we think that master isn't running.
391 # ...but before actually starting a master, we'll double-check. This can
392 # be important because we can't tell that that 'git@myhost.com' is the same
393 # as 'myhost.com' where "User git" is setup in the user's ~/.ssh/config file.
394 check_command = command_base + ['-O','check']
395 try:
396 Trace(': %s', ' '.join(check_command))
397 check_process = subprocess.Popen(check_command,
398 stdout=subprocess.PIPE,
399 stderr=subprocess.PIPE)
400 check_process.communicate() # read output, but ignore it...
401 isnt_running = check_process.wait()
402
403 if not isnt_running:
404 # Our double-check found that the master _was_ infact running. Add to
405 # the list of keys.
406 _master_keys.add(key)
407 return True
408 except Exception:
409 # Ignore excpetions. We we will fall back to the normal command and print
410 # to the log there.
411 pass
412
413 command = command_base[:1] + \
414 ['-M', '-N'] + \
415 command_base[1:]
389 try: 416 try:
390 Trace(': %s', ' '.join(command)) 417 Trace(': %s', ' '.join(command))
391 p = subprocess.Popen(command) 418 p = subprocess.Popen(command)
@@ -396,20 +423,22 @@ def _open_ssh(host, port=None):
396 % (host,port, str(e)) 423 % (host,port, str(e))
397 return False 424 return False
398 425
399 _ssh_cache[key] = p 426 _master_processes.append(p)
427 _master_keys.add(key)
400 time.sleep(1) 428 time.sleep(1)
401 return True 429 return True
402 430
403def close_ssh(): 431def close_ssh():
404 terminate_ssh_clients() 432 terminate_ssh_clients()
405 433
406 for key,p in _ssh_cache.iteritems(): 434 for p in _master_processes:
407 try: 435 try:
408 os.kill(p.pid, SIGTERM) 436 os.kill(p.pid, SIGTERM)
409 p.wait() 437 p.wait()
410 except OSError: 438 except OSError:
411 pass 439 pass
412 _ssh_cache.clear() 440 del _master_processes[:]
441 _master_keys.clear()
413 442
414 d = ssh_sock(create=False) 443 d = ssh_sock(create=False)
415 if d: 444 if d: