2012-02-08 4 views
0

поэтому мой проект структурирован так, как следует. У меня есть вишневый сервер и серверный сервер, который выполняет некоторую операцию. Теперь у меня есть «основной» файл app.py, который обрабатывает эти процессы. Они начали как:странная ситуация с правами доступа к файлам на окнах

SERVER = subprocess.Popen([PYTHON_EXE_PATH, '-m', WEB_SERVER, 
            'tvb'], shell=False) 

    BACKEND = subprocess.Popen([PYTHON_EXE_PATH, '-m', 'bin.rpserver' 
          , cfg.RPC_SERVER_IP, cfg.RPC_SERVER_PORT], 
          shell=False) 

Теперь после того, как они начали этот ИДП хранится в файл, так что пользователь может запустить сценарий остановки и закрыть их. Этот сценарий также хорошо работает и в основном:

def execute_stop(): 
    if os.path.exists(PID_FILE): 
     pid_file = open(PID_FILE, 'r') 
     has_processes = False 
     for pid in pid_file.read().split('\n'): 
      if len(pid.strip()): 
       try: 
        if sys.platform == 'win32': 
         import ctypes 
         handle = ctypes.windll.kernel32.OpenProcess(1, False, 
                   int(pid)) 
         ctypes.windll.kernel32.TerminateProcess(handle, -1) 
         ctypes.windll.kernel32.CloseHandle(handle) 
        else: 
         os.kill(int(pid), signal.SIGKILL) 
       except Exception, _: 
        has_processes = True 
     if has_processes: 
      sys.stdout.write("Some old PIDs were still registered; \ 
          They could not be stopped.")      
     pid_file.close() 
    pid_file = open(PID_FILE, "w") 
    pid_file.close() 

Сейчас этот PID-файл, вместе с моим файлом регистратор и другими файлами данные, которые создаются проводится в cfg.STORAGE, и я также имеет простую чистую процедуру, которая :

def execute_clean(): 
    """Remove TVB folder, TVB File DB, and log file.""" 
    try: 
     if os.path.isdir(cfg.TVB_STORAGE): 
      shutil.rmtree(cfg.TVB_STORAGE) 
    except Exception, excep1: 
     sys.stdout.write("Could not remove storage folder!") 
     sys.stdout.write(str(excep1)) 

Это также отлично работает при вызове отдельно. Но вот в чем проблема: в моей программе есть опция, которая позволяет пользователю изменять некоторые настройки, и в этом случае вся программа должна перезагрузиться и шаги должны быть переделаны. Для этого я:

cherrypy.engine.exit() 
    self.logger.debug("Waiting for Cherrypy to terminate.") 
    sleep(2) 
    python_path = cfg().get_python_path() 
    proc_params = [python_path, '-m', 'bin.app', 'start', 'web', 'backend'] 
    subprocess.Popen(proc_params, shell=False) 

Так что это будет опять же в основном следующие шаги:

execute_stop() 
    execute_clean() 
    start both processes again 

Странная вещь, что я не могу понять, что execute_stop() работает отлично, и как вы можете видеть на конец PID_FILE открыт в режиме записи и закрыт для очистки содержимого, но затем сразу после execute_clean() не может сказать, что PID_FILE заблокирован другим процессом.

Теперь я проверил и перепроверял, и каждый раз, когда этот файл открывается, он закрыт после, и я действительно не знаю, что искать. Это происходит только в окнах, и я пробовал использовать хост зависимостей, чтобы увидеть, что происходит, и кажется, что когда процессы python работают, зависимый ходок видит 4 ссылки и 2 обработчика для этих файлов, что странно, учитывая, что они закрываются каждый раз. Мне также кажется странным, что я могу открыть файлы в режиме 'w', но я не могу их удалить.

Любые идеи, что может быть неправильным/что искать, будут действительно оценены.

EDIT

Я пытался использовать в качестве мотивационные os.waitpid, но при выполнении:

os.waitpid(int(pid), 0) 

Я получил [Errno 10] No child processes. Я также читал и видел, как кто-то говорит, что в окнах вы должны передать дескриптор вместо pid в os.waitpid, чтобы я также попробовал его с помощью дескриптора, но я получил тот же результат. Итак, в этот момент процесс больше не должен существовать?

ответ

0

Это только выстрел в темноте ...
Моя догадка заключается в том, что один или оба процесса SERVER, BACKEND не заканчиваются так, как ожидалось, и имеют открытый PID_FILE. Убедитесь, что каждый из них открывает PID_FILE с помощью mode='a' и быстро закроет его. Если я не с базы с тем, как SERVER/BACKEND обрабатывает PID_FILE, вы также можете попробовать os.waitpid(pid) после вашего звонка на TerminateProcess. Это должно блокироваться до тех пор, пока процесс не будет действительно прекращен.

Смежные вопросы