Mercurial > hg
comparison hgext/blackbox.py @ 34109:cf04db16f583
blackbox: do not cache file objects
Having the blackbox file objects cached in `ui._bbfp` could in theory be
troublesome if multiple processes (ex. chg servers) have file objects
referring to a same file. (Although I spent some time and failed to build a
convincing test case)
This patch makes blackbox re-open the file every time to make the situation
better. Ideally we also need proper locking.
The caching logic traces back to the commit introducing blackbox
(18242716a). That commit does not have details about why caching is
necessary. Consider the fact that blackbox logs are not many, it seems fine
to remove the fp cache to be more confident.
Differential Revision: https://phab.mercurial-scm.org/D650
author | Jun Wu <quark@fb.com> |
---|---|
date | Wed, 06 Sep 2017 21:08:59 -0700 |
parents | 50df6cf22717 |
children | 029b33adbd17 |
comparison
equal
deleted
inserted
replaced
34108:50df6cf22717 | 34109:cf04db16f583 |
---|---|
78 def __init__(self, src=None): | 78 def __init__(self, src=None): |
79 super(blackboxui, self).__init__(src) | 79 super(blackboxui, self).__init__(src) |
80 if src is None: | 80 if src is None: |
81 self._partialinit() | 81 self._partialinit() |
82 else: | 82 else: |
83 self._bbfp = getattr(src, '_bbfp', None) | |
84 self._bbinlog = False | 83 self._bbinlog = False |
85 self._bbrepo = getattr(src, '_bbrepo', None) | 84 self._bbrepo = getattr(src, '_bbrepo', None) |
86 self._bbvfs = getattr(src, '_bbvfs', None) | 85 self._bbvfs = getattr(src, '_bbvfs', None) |
87 | 86 |
88 def _partialinit(self): | 87 def _partialinit(self): |
89 if util.safehasattr(self, '_bbvfs'): | 88 if util.safehasattr(self, '_bbvfs'): |
90 return | 89 return |
91 self._bbfp = None | |
92 self._bbinlog = False | 90 self._bbinlog = False |
93 self._bbrepo = None | 91 self._bbrepo = None |
94 self._bbvfs = None | 92 self._bbvfs = None |
95 | 93 |
96 def copy(self): | 94 def copy(self): |
141 self._partialinit() | 139 self._partialinit() |
142 | 140 |
143 if not '*' in self.track and not event in self.track: | 141 if not '*' in self.track and not event in self.track: |
144 return | 142 return |
145 | 143 |
146 if self._bbfp: | 144 if self._bbvfs: |
147 ui = self | |
148 elif self._bbvfs: | |
149 try: | |
150 self._bbfp = self._openlogfile() | |
151 except (IOError, OSError) as err: | |
152 self.debug('warning: cannot write to blackbox.log: %s\n' % | |
153 err.strerror) | |
154 del self._bbvfs | |
155 self._bbfp = None | |
156 ui = self | 145 ui = self |
157 else: | 146 else: |
158 # certain ui instances exist outside the context of | 147 # certain ui instances exist outside the context of |
159 # a repo, so just default to the last blackbox that | 148 # a repo, so just default to the last blackbox that |
160 # was seen. | 149 # was seen. |
161 ui = lastui | 150 ui = lastui |
162 | 151 |
163 if not ui or not ui._bbfp: | 152 if not ui: |
164 return | 153 return |
165 if not lastui or ui._bbrepo: | 154 if not lastui or ui._bbrepo: |
166 lastui = ui | 155 lastui = ui |
167 if ui._bbinlog: | 156 if ui._bbinlog: |
168 # recursion guard | 157 # recursion and failure guard |
169 return | 158 return |
170 try: | 159 try: |
171 ui._bbinlog = True | 160 ui._bbinlog = True |
172 default = self.configdate('devel', 'default-date') | 161 default = self.configdate('devel', 'default-date') |
173 date = util.datestr(default, '%Y/%m/%d %H:%M:%S') | 162 date = util.datestr(default, '%Y/%m/%d %H:%M:%S') |
186 if ui.configbool('blackbox', 'logsource'): | 175 if ui.configbool('blackbox', 'logsource'): |
187 src = ' [%s]' % event | 176 src = ' [%s]' % event |
188 else: | 177 else: |
189 src = '' | 178 src = '' |
190 try: | 179 try: |
191 fp = ui._bbfp | |
192 fmt = '%s %s @%s%s (%s)%s> %s' | 180 fmt = '%s %s @%s%s (%s)%s> %s' |
193 args = (date, user, rev, changed, pid, src, formattedmsg) | 181 args = (date, user, rev, changed, pid, src, formattedmsg) |
194 fp.write(fmt % args) | 182 with ui._openlogfile() as fp: |
195 fp.flush() | 183 fp.write(fmt % args) |
196 except IOError as err: | 184 except (IOError, OSError) as err: |
197 self.debug('warning: cannot write to blackbox.log: %s\n' % | 185 self.debug('warning: cannot write to blackbox.log: %s\n' % |
198 err.strerror) | 186 err.strerror) |
187 # do not restore _bbinlog intentionally to avoid failed | |
188 # logging again | |
189 else: | |
190 ui._bbinlog = False | |
199 finally: | 191 finally: |
200 ui._bbinlog = False | 192 pass |
201 | 193 |
202 def setrepo(self, repo): | 194 def setrepo(self, repo): |
203 self._bbfp = None | |
204 self._bbinlog = False | 195 self._bbinlog = False |
205 self._bbrepo = repo | 196 self._bbrepo = repo |
206 self._bbvfs = repo.vfs | 197 self._bbvfs = repo.vfs |
207 | 198 |
208 ui.__class__ = blackboxui | 199 ui.__class__ = blackboxui |