]> git.phdru.name Git - bookmarks_db.git/blob - Robots/bkmk_rforking.py
Style: Fix flake8 E261 at least two spaces before inline comment
[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 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(
64                     ['='.join((k, v)) for k, v in subproc_attrs]
65                 )
66             os.environ['BKMK_ROBOT'] = subproc
67
68         if not check_subp:
69             restart_subp(self.log)  # Not restart, just start afresh
70
71         try:
72             save_parent = bookmark.parent
73             bookmark.parent = None
74             subp_pipe.write_record(pickle.dumps(bookmark))
75
76             if check_subp.waitForPendingChar(60):  # wait a minute
77                 new_b = pickle.loads(subp_pipe.read_record())
78                 for attr in (
79                     "error", "no_error",
80                     "moved", "size", "md5", "real_title",
81                     "last_tested", "last_modified", "test_time",
82                     "icon", "icon_href",
83                 ):
84                     if hasattr(new_b, attr):
85                         setattr(bookmark, attr, getattr(new_b, attr))
86             else:
87                 bookmark.error = "Subprocess connection timed out"
88                 restart_subp(self.log)
89
90             bookmark.parent = save_parent
91
92             while True:
93                 error = check_subp.readPendingErrLine()
94                 if not error:
95                     break
96                 sys.stderr.write("(subp) " + error)
97             sys.stderr.flush()
98
99         except KeyboardInterrupt:
100             return 0
101
102         # Tested
103         return 1
104
105     def stop(self):
106         stop_subp(None)  # Stop subprocess; do not log restarting