]> git.phdru.name Git - bookmarks_db.git/blob - Robots/bkmk_rforking.py
Style: Fix flake8 E302 expected 2 blank lines, found 1
[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-2023 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
32 def stop_subp(log):
33     global check_subp, subp_pipe
34     if check_subp:
35         if log: log("   restarting hanging subprocess")
36         del check_subp
37     del subp_pipe
38
39
40 def restart_subp(log):
41     global check_subp, subp_pipe
42     stop_subp(log)
43
44     check_subp = Subprocess("%s/Robots/bkmk_rforking_sub.py" % os.path.dirname(sys.argv[0]),
45                             control_stderr=True)
46     subp_pipe = RecordFile(check_subp)
47
48
49 _set_subproc = True
50
51
52 class robot_forking(Robot):
53     subproc = 'urllib2'  # Default subprocess
54
55     def check_url(self, bookmark):
56         global _set_subproc
57         if _set_subproc:
58             _set_subproc = False
59
60             subproc = self.subproc
61             subproc_attrs = []
62             for attr in dir(self):
63                 if attr.startswith('subproc_'):
64                     subproc_attrs.append((attr[len('subproc_'):], getattr(self, attr)))
65             if subproc_attrs:
66                 subproc += ':' + ':'.join(
67                     ['='.join((k, v)) for k, v in subproc_attrs]
68                 )
69             os.environ['BKMK_ROBOT'] = subproc
70
71         if not check_subp:
72             restart_subp(self.log)  # Not restart, just start afresh
73
74         try:
75             save_parent = bookmark.parent
76             bookmark.parent = None
77             subp_pipe.write_record(pickle.dumps(bookmark))
78
79             if check_subp.waitForPendingChar(60):  # wait a minute
80                 new_b = pickle.loads(subp_pipe.read_record())
81                 for attr in (
82                     "error", "no_error",
83                     "moved", "size", "md5", "real_title",
84                     "last_tested", "last_modified", "test_time",
85                     "icon", "icon_href",
86                 ):
87                     if hasattr(new_b, attr):
88                         setattr(bookmark, attr, getattr(new_b, attr))
89             else:
90                 bookmark.error = "Subprocess connection timed out"
91                 restart_subp(self.log)
92
93             bookmark.parent = save_parent
94
95             while True:
96                 error = check_subp.readPendingErrLine()
97                 if not error:
98                     break
99                 sys.stderr.write("(subp) " + error)
100             sys.stderr.flush()
101
102         except KeyboardInterrupt:
103             return 0
104
105         # Tested
106         return 1
107
108     def stop(self):
109         stop_subp(None)  # Stop subprocess; do not log restarting