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