comparison plugin/autotags.vim @ 15:b557282af215

Fix race condition between the statusline and the lock file.
author Ludovic Chabant <ludovic@chabant.com>
date Tue, 29 Jul 2014 16:11:24 -0700
parents b8f23bf7b20f
children c11616828595
comparison
equal deleted inserted replaced
14:b8f23bf7b20f 15:b557282af215
203 if has('win32') 203 if has('win32')
204 let s:runner_exe = expand('<sfile>:h:h') . '\plat\win32\update_tags.cmd' 204 let s:runner_exe = expand('<sfile>:h:h') . '\plat\win32\update_tags.cmd'
205 endif 205 endif
206 206
207 let s:update_queue = [] 207 let s:update_queue = []
208 let s:maybe_in_progress = [] 208 let s:maybe_in_progress = {}
209 209
210 " Get how to execute an external command depending on debug settings. 210 " Get how to execute an external command depending on debug settings.
211 function! s:get_execute_cmd() abort 211 function! s:get_execute_cmd() abort
212 if has('win32') 212 if has('win32')
213 let l:cmd = '!start ' 213 let l:cmd = '!start '
317 let l:cmd .= ' > /dev/null 2>&1' 317 let l:cmd .= ' > /dev/null 2>&1'
318 endif 318 endif
319 endif 319 endif
320 let l:cmd .= s:get_execute_cmd_suffix() 320 let l:cmd .= s:get_execute_cmd_suffix()
321 321
322 " Run the background process.
323 call s:trace("Running: " . l:cmd) 322 call s:trace("Running: " . l:cmd)
324 call s:trace("In: " . l:work_dir) 323 call s:trace("In: " . l:work_dir)
325 if !g:autotags_fake 324 if !g:autotags_fake
326 " Flag this tags file as being in progress 325 " Run the background process.
327 call add(s:maybe_in_progress, fnamemodify(l:tags_file, ':p'))
328
329 if !g:autotags_trace 326 if !g:autotags_trace
330 silent execute l:cmd 327 silent execute l:cmd
331 else 328 else
332 execute l:cmd 329 execute l:cmd
333 endif 330 endif
331
332 " Flag this tags file as being in progress
333 let l:full_tags_file = fnamemodify(l:tags_file, ':p')
334 let s:maybe_in_progress[l:full_tags_file] = localtime()
334 else 335 else
335 call s:trace("(fake... not actually running)") 336 call s:trace("(fake... not actually running)")
336 endif 337 endif
337 call s:trace("") 338 call s:trace("")
338 finally 339 finally
407 echom "" 408 echom ""
408 endfunction 409 endfunction
409 410
410 function! autotags#inprogress() 411 function! autotags#inprogress()
411 echom "autotags: generations in progress:" 412 echom "autotags: generations in progress:"
412 for mip in s:maybe_in_progress 413 for mip in keys(s:maybe_in_progress)
413 echom mip 414 echom mip
414 endfor 415 endfor
415 echom "" 416 echom ""
416 endfunction 417 endfunction
417 418
426 " - args 1 and 2 are the prefix and suffix, respectively, of whatever output, 427 " - args 1 and 2 are the prefix and suffix, respectively, of whatever output,
427 " if any, is going to be produced. 428 " if any, is going to be produced.
428 " (defaults to empty strings) 429 " (defaults to empty strings)
429 " - arg 3 is the text to be shown if tags are currently being generated. 430 " - arg 3 is the text to be shown if tags are currently being generated.
430 " (defaults to 'TAGS') 431 " (defaults to 'TAGS')
431 " 432
432 function! autotags#statusline(...) abort 433 function! autotags#statusline(...) abort
433 if !exists('b:autotags_file') 434 if !exists('b:autotags_file')
434 " This buffer doesn't have autotags. 435 " This buffer doesn't have autotags.
435 return '' 436 return ''
436 endif 437 endif
444 " To make this function as fast as possible, we first check whether the 445 " To make this function as fast as possible, we first check whether the
445 " current buffer's tags file is 'maybe' being generated. This provides a 446 " current buffer's tags file is 'maybe' being generated. This provides a
446 " nice and quick bail out for 99.9% of cases before we need to this the 447 " nice and quick bail out for 99.9% of cases before we need to this the
447 " file-system to check the lock file. 448 " file-system to check the lock file.
448 let l:abs_tag_file = fnamemodify(b:autotags_file, ':p') 449 let l:abs_tag_file = fnamemodify(b:autotags_file, ':p')
449 let l:found = index(s:maybe_in_progress, l:abs_tag_file) 450 let l:timestamp = get(s:maybe_in_progress, l:abs_tag_file)
450 if l:found < 0 451 if l:timestamp == 0
451 return '' 452 return ''
452 endif 453 endif
453 " It's maybe generating! Check if the lock file is still there. 454 " It's maybe generating! Check if the lock file is still there... but
454 if !filereadable(l:abs_tag_file . '.lock') 455 " don't do it too soon after the script was originally launched, because
455 call remove(s:maybe_in_progress, l:found) 456 " there can be a race condition where we get here just before the script
457 " had a chance to write the lock file.
458 if (localtime() - l:timestamp) > 1 &&
459 \!filereadable(l:abs_tag_file . '.lock')
460 call remove(s:maybe_in_progress, l:abs_tag_file)
456 return '' 461 return ''
457 endif 462 endif
458 " It's still there! So probably `ctags` is still running... 463 " It's still there! So probably `ctags` is still running...
459 " (although there's a chance it crashed, or the script had a problem, and 464 " (although there's a chance it crashed, or the script had a problem, and
460 " the lock file has been left behind... we could try and run some 465 " the lock file has been left behind... we could try and run some