Bram Moolenaar wrote:

> Dominique Pelle wrote:
>
>> Attached patch fixes a race condition which causes Vim to hang
>> when resuming (with fg) after having suspended Vim with CTRL-Z.
>> Bug does not happen 100% of the time, but once in a while.  I
>> can reproduce the bug with Vim-7.2.121 in a xterm on Linux x86
>> after doing
>>
>> CTRL-Z
>> fg
>> CTRL-Z
>> fg
>> , etc, ... several times until Vim hangs.
>>
>> Pressing CTRL-C is a workaround when it hangs.
>>
>> See also Ubuntu bug https://bugs.launchpad.net/bugs/291373
>>
>> Bug only happens when configure script defined -D_REENTRANT
>> which happens at least when I configure Vim as follows:
>>
>>  ./configure --enable-tclinterp --enable-rubyinterp \
>>    --enable-perlinterp  --enable-pythoninterp \
>>   --with-features=huge --enable-gui=gnome2
>>
>> The problem happens I think because the following 2 lines
>> in os_unix.c in mch_suspect() have a race condition:
>>
>>     if (!sigcont_received)
>>       pause();
>>
>> If the signal is handled _after_ the test of sigcont_received
>> variable but _before_ pause() is executed, then pause() will
>> wait for ever since signal already happened.
>>
>> Also I think that the variable sigcont_received should also be
>> declared volatile since it's modified by a signal handler.
>>
>> Attached patch fixes the race condition by waiting until
>> sigcont_received is set without calling pause():
>>
>>       long wait;
>>       for (wait = 0; !sigcont_received && wait <= 3L; wait++)
>>           /* Loop is not entered most of the time */
>>           mch_delay(wait, FALSE);
>>
>> Note that most of the time the loop does not even need
>> to sleep() at all (sigcont_received is already set most of
>> the time before entering the loop).  And when it it sleeps,
>> a sleep(0) seems always enough in practice.  I've put
>> debug printf() after the loop that waits for sigcont_received
>> and I see this when doing several suspend (CTRL-Z, fg):
>>
>> **** wait=0
>> **** wait=0
>> **** wait=0
>> **** wait=0
>> **** wait=0
>> **** wait=0
>> **** wait=0
>> **** wait=1
>> **** wait=0
>> **** wait=0
>> **** wait=0
>> **** wait=0
>> **** wait=0
>> **** wait=1
>> **** wait=0
>> **** wait=0
>> **** wait=0
>> **** wait=0
>>
>> Notice that in 2 occasions, wait was 1 (meaning that the loop
>> iterated once with a sleep of 0 (yielding the CPU which is
>> enough to get the signal handled).
>
> Makes sense.  Perhaps pause() does some work that increases the change
> for the race condition to actually happen (e.g., a aquiring a lock).
>
> One problem: the Vim code doesn't use volatile yet.  I don't think every
> C compiler supports it, thus this requires adding a configure check.
> AC_C_VOLATILE will do.


OK.  I'm no expert with configure scripts, but I assume that
what you're asking is what the extra attached patch does.

Without marking the variable volatile, there is a risk I think,
that some compilers might optimize making code incorrect
sometimes by not seeing that the variable gets automagically
updated asynchronously by a signal handler as explained here
for example:

http://www.linuxdevices.com/articles/AT5980346182.html

These kind of bugs can be subtle and hard to reproduce.

I also see other variables in Vim which are modified or read
by signal handlers. They should in theory also be declared
volatile:

- do_resize (modified by signal handler sig_winch())
- got_int  (modified by signal handler catch_sigint())
- sig_alarm_called (modified by signal handler sig_alarm())
- full_screen (modified by signal handler deathtrap())
- in_mch_delay (read by signal handler deathtrap())
- lc_active (read by signal handler deathtrap())
- sigcont_received (modified by signal handler sigcont_handler())
(maybe others)

Cheers
-- Dominique

--~--~---------~--~----~------------~-------~--~----~
You received this message from the "vim_dev" maillist.
For more information, visit http://www.vim.org/maillist.php
-~----------~----~----~----~------~----~------~--~---

Index: configure.in
===================================================================
RCS file: /cvsroot/vim/vim7/src/configure.in,v
retrieving revision 1.66
diff -c -r1.66 configure.in
*** configure.in	20 Nov 2008 09:36:35 -0000	1.66
--- configure.in	22 Feb 2009 22:35:28 -0000
***************
*** 2148,2153 ****
--- 2148,2154 ----
  dnl Checks for typedefs, structures, and compiler characteristics.
  AC_PROG_GCC_TRADITIONAL
  AC_C_CONST
+ AC_C_VOLATILE
  AC_TYPE_MODE_T
  AC_TYPE_OFF_T
  AC_TYPE_PID_T
Index: config.h.in
===================================================================
RCS file: /cvsroot/vim/vim7/src/config.h.in,v
retrieving revision 1.11
diff -c -r1.11 config.h.in
*** config.h.in	24 Jun 2008 21:47:46 -0000	1.11
--- config.h.in	22 Feb 2009 22:35:28 -0000
***************
*** 50,55 ****
--- 50,58 ----
  /* Define to empty if the keyword does not work.  */
  #undef const
  
+ /* Define to empty if the keyword does not work.  */
+ #undef volatile
+ 
  /* Define to `int' if <sys/types.h> doesn't define.  */
  #undef mode_t
  

Raspunde prin e-mail lui