]> git.phdru.name Git - bookmarks_db.git/blob - Robots/bkmk_rforking.py
4ad998403417398b15643f3de2809c4c7c382f22
[bookmarks_db.git] / Robots / bkmk_rforking.py
1 """Forking robot
2
3 This file is a part of Bookmarks database and Internet robot.
4 """
5
6 __author__ = "Oleg Broytman <phd@phdru.name>"
7 __copyright__ = "Copyright (C) 2000-2012 PhiloSoft Design"
8 __license__ = "GNU GPL"
9
10 __all__ = ['robot_forking']
11
12
13 import sys, os
14
15 try:
16    import cPickle as pickle
17 except ImportError:
18    import pickle
19
20 from subproc import Subprocess, RecordFile
21 from bkmk_objects import Robot
22
23
24 # This is to catch 'close failed: [Errno 9] Bad file descriptor' message
25 # from os.close() in Subprocess.die() and errors from the subprocess.
26 sys.stderr = open("err.log", 'a')
27
28 check_subp = None
29 subp_pipe = None
30
31 def stop_subp(log):
32    global check_subp, subp_pipe
33    if check_subp:
34       if log: log("   restarting hanging subprocess")
35       del check_subp
36    del subp_pipe
37
38 def restart_subp(log):
39    global check_subp, subp_pipe
40    stop_subp(log)
41
42    check_subp = Subprocess("%s/Robots/bkmk_rforking_sub.py" % os.path.dirname(sys.argv[0]),
43       control_stderr=True)
44    subp_pipe = RecordFile(check_subp)
45
46
47 _set_subproc = True
48
49 class robot_forking(Robot):
50    subproc = 'urllib2' # Default subprocess
51
52    def check_url(self, bookmark):
53       global _set_subproc
54       if _set_subproc:
55          _set_subproc = False
56
57          subproc = self.subproc
58          subproc_attrs = []
59          for attr in dir(self):
60              if attr.startswith('subproc_'):
61                  subproc_attrs.append((attr[len('subproc_'):], getattr(self, attr)))
62          if subproc_attrs:
63              subproc += ':' + ':'.join(['='.join((k,v)) for k,v in subproc_attrs])
64          os.environ['BKMK_ROBOT'] = subproc
65
66       if not check_subp:
67          restart_subp(self.log) # Not restart, just start afresh
68
69       try:
70          save_parent = bookmark.parent
71          bookmark.parent = None
72          subp_pipe.write_record(pickle.dumps(bookmark))
73
74          if check_subp.waitForPendingChar(60): # wait a minute
75             new_b = pickle.loads(subp_pipe.read_record())
76             for attr in ("error", "no_error",
77                   "moved", "size", "md5", "real_title",
78                   "last_tested", "last_modified", "test_time",
79                   "icon", "icon_href"):
80                if hasattr(new_b, attr):
81                   setattr(bookmark, attr, getattr(new_b, attr))
82          else:
83             bookmark.error = "Subprocess connection timed out"
84             restart_subp(self.log)
85
86          bookmark.parent = save_parent
87
88          while True:
89             error = check_subp.readPendingErrLine()
90             if not error:
91                break
92             sys.stderr.write("(subp) " + error)
93          sys.stderr.flush()
94
95       except KeyboardInterrupt:
96          return 0
97
98       # Tested
99       return 1
100
101    def stop(self):
102       stop_subp(None) # Stop subprocess; do not log restarting