Show More
@@ -23,6 +23,8 b' import re' | |||||
23 | import shutil |
|
23 | import shutil | |
24 | import sys |
|
24 | import sys | |
25 |
|
25 | |||
|
26 | from subprocess import Popen, PIPE | |||
|
27 | ||||
26 | from IPython.config.loader import PyFileConfigLoader |
|
28 | from IPython.config.loader import PyFileConfigLoader | |
27 | from IPython.config.configurable import Configurable |
|
29 | from IPython.config.configurable import Configurable | |
28 | from IPython.core.application import Application, BaseAppConfigLoader |
|
30 | from IPython.core.application import Application, BaseAppConfigLoader | |
@@ -534,4 +536,31 b' class ApplicationWithClusterDir(Application):' | |||||
534 | return pid |
|
536 | return pid | |
535 | else: |
|
537 | else: | |
536 | raise PIDFileError('pid file not found: %s' % pid_file) |
|
538 | raise PIDFileError('pid file not found: %s' % pid_file) | |
537 |
|
539 | |||
|
540 | def check_pid(self, pid): | |||
|
541 | if os.name == 'nt': | |||
|
542 | try: | |||
|
543 | import ctypes | |||
|
544 | # returns 0 if no such process (of ours) exists | |||
|
545 | # positive int otherwise | |||
|
546 | p = ctypes.windll.kernel32.OpenProcess(1,0,pid) | |||
|
547 | except Exception: | |||
|
548 | self.log.warn( | |||
|
549 | "Could not determine whether pid %i is running via `OpenProcess`. " | |||
|
550 | " Making the likely assumption that it is."%pid | |||
|
551 | ) | |||
|
552 | return True | |||
|
553 | return bool(p) | |||
|
554 | else: | |||
|
555 | try: | |||
|
556 | p = Popen(['ps','x'], stdout=PIPE, stderr=PIPE) | |||
|
557 | output,_ = p.communicate() | |||
|
558 | except OSError: | |||
|
559 | self.log.warn( | |||
|
560 | "Could not determine whether pid %i is running via `ps x`. " | |||
|
561 | " Making the likely assumption that it is."%pid | |||
|
562 | ) | |||
|
563 | return True | |||
|
564 | pids = map(int, re.findall(r'^\W*\d+', output, re.MULTILINE)) | |||
|
565 | return pid in pids | |||
|
566 | No newline at end of file |
@@ -21,6 +21,7 b' import os' | |||||
21 | import re |
|
21 | import re | |
22 | import signal |
|
22 | import signal | |
23 |
|
23 | |||
|
24 | from subprocess import check_call, CalledProcessError, PIPE | |||
24 | import zmq |
|
25 | import zmq | |
25 | from zmq.eventloop import ioloop |
|
26 | from zmq.eventloop import ioloop | |
26 |
|
27 | |||
@@ -497,13 +498,17 b' class IPClusterApp(ApplicationWithClusterDir):' | |||||
497 | except PIDFileError: |
|
498 | except PIDFileError: | |
498 | pass |
|
499 | pass | |
499 | else: |
|
500 | else: | |
500 |
self. |
|
501 | if self.check_pid(pid): | |
501 | 'Cluster is already running with [pid=%s]. ' |
|
502 | self.log.critical( | |
502 | 'use "ipcluster stop" to stop the cluster.' % pid |
|
503 | 'Cluster is already running with [pid=%s]. ' | |
503 | ) |
|
504 | 'use "ipcluster stop" to stop the cluster.' % pid | |
504 | # Here I exit with a unusual exit status that other processes |
|
505 | ) | |
505 | # can watch for to learn how I existed. |
|
506 | # Here I exit with a unusual exit status that other processes | |
506 | self.exit(ALREADY_STARTED) |
|
507 | # can watch for to learn how I existed. | |
|
508 | self.exit(ALREADY_STARTED) | |||
|
509 | else: | |||
|
510 | self.remove_pid_file() | |||
|
511 | ||||
507 |
|
512 | |||
508 | # Now log and daemonize |
|
513 | # Now log and daemonize | |
509 | self.log.info( |
|
514 | self.log.info( | |
@@ -526,7 +531,8 b' class IPClusterApp(ApplicationWithClusterDir):' | |||||
526 | pass |
|
531 | pass | |
527 | else: |
|
532 | else: | |
528 | raise |
|
533 | raise | |
529 | self.remove_pid_file() |
|
534 | finally: | |
|
535 | self.remove_pid_file() | |||
530 |
|
536 | |||
531 | def start_app_engines(self): |
|
537 | def start_app_engines(self): | |
532 | """Start the app for the start subcommand.""" |
|
538 | """Start the app for the start subcommand.""" | |
@@ -563,23 +569,41 b' class IPClusterApp(ApplicationWithClusterDir):' | |||||
563 | pid = self.get_pid_from_file() |
|
569 | pid = self.get_pid_from_file() | |
564 | except PIDFileError: |
|
570 | except PIDFileError: | |
565 | self.log.critical( |
|
571 | self.log.critical( | |
566 |
' |
|
572 | 'Could not read pid file, cluster is probably not running.' | |
567 | ) |
|
573 | ) | |
568 | # Here I exit with a unusual exit status that other processes |
|
574 | # Here I exit with a unusual exit status that other processes | |
569 | # can watch for to learn how I existed. |
|
575 | # can watch for to learn how I existed. | |
|
576 | self.remove_pid_file() | |||
570 | self.exit(ALREADY_STOPPED) |
|
577 | self.exit(ALREADY_STOPPED) | |
571 |
|
|
578 | ||
572 | if os.name=='posix': |
|
579 | if not self.check_pid(pid): | |
573 | sig = config.Global.signal |
|
580 | self.log.critical( | |
574 | self.log.info( |
|
581 | 'Cluster [pid=%r] is not running.' % pid | |
575 | "Stopping cluster [pid=%r] with [signal=%r]" % (pid, sig) |
|
582 | ) | |
576 | ) |
|
583 | self.remove_pid_file() | |
|
584 | # Here I exit with a unusual exit status that other processes | |||
|
585 | # can watch for to learn how I existed. | |||
|
586 | self.exit(ALREADY_STOPPED) | |||
|
587 | ||||
|
588 | elif os.name=='posix': | |||
|
589 | sig = config.Global.signal | |||
|
590 | self.log.info( | |||
|
591 | "Stopping cluster [pid=%r] with [signal=%r]" % (pid, sig) | |||
|
592 | ) | |||
|
593 | try: | |||
577 | os.kill(pid, sig) |
|
594 | os.kill(pid, sig) | |
578 | elif os.name=='nt': |
|
595 | except OSError: | |
579 | # As of right now, we don't support daemonize on Windows, so |
|
596 | self.log.error("Stopping cluster failed, assuming already dead.", | |
580 | # stop will not do anything. Minimally, it should clean up the |
|
597 | exc_info=True) | |
581 | # old .pid files. |
|
|||
582 | self.remove_pid_file() |
|
598 | self.remove_pid_file() | |
|
599 | elif os.name=='nt': | |||
|
600 | try: | |||
|
601 | # kill the whole tree | |||
|
602 | p = check_call(['taskkill', '-pid', str(pid), '-t', '-f'], stdout=PIPE,stderr=PIPE) | |||
|
603 | except (CalledProcessError, OSError): | |||
|
604 | self.log.error("Stopping cluster failed, assuming already dead.", | |||
|
605 | exc_info=True) | |||
|
606 | self.remove_pid_file() | |||
583 |
|
607 | |||
584 |
|
608 | |||
585 | def launch_new_instance(): |
|
609 | def launch_new_instance(): |
General Comments 0
You need to be logged in to leave comments.
Login now