help-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Help-bash] Why is "volatile" used in bash source code?


From: Eric Blake
Subject: Re: [Help-bash] Why is "volatile" used in bash source code?
Date: Wed, 6 Feb 2019 17:06:33 -0600
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.4.0

On 2/6/19 3:02 PM, Peng Yu wrote:
>> Now, if you ask about a PARTICULAR file/function/line of code that uses
>> volatile, I can give you more details why that particular use requires
>> the keyword.
> 
> For example, the following lines in main() of shell.c. If they are not
> "volatile", what will happen?
> 
>  370   volatile int locally_skip_execution;
>  371   volatile int arg_index, top_level_arg_index;

Well, let's look at the context:

int
main (argc, argv, env)
     int argc;
     char **argv, **env;
#endif /* !NO_MAIN_ENV_ARG */
{
  register int i;
  int code, old_errexit_flag;
#if defined (RESTRICTED_SHELL)
  int saverst;
#endif
  volatile int locally_skip_execution;
  volatile int arg_index, top_level_arg_index;
...
  /* Initialize `local' variables for all `invocations' of main (). */
  arg_index = 1;
  if (arg_index > argc)
    arg_index = argc;
...

  if (shell_initialized || shell_name)
    {
      /* Make sure that we do not infinitely recurse as a login shell. */
      if (*shell_name == '-')
        shell_name++;

      shell_reinitialize ();
      if (setjmp_nosigs (top_level))
        exit (2);
    }


  shell_environment = env;
  set_shell_name (argv[0]);
  shell_start_time = NOW;       /* NOW now defined in general.h */

  /* Parse argument flags from the input line. */

  /* Find full word arguments first. */
  arg_index = parse_long_options (argv, arg_index, argc);


See that call to setjmp_nosigs()? That's a point of non-local
modification - everything that is stored in local variables is saved off
into the setjmp() state, then we CHANGE those local variables, and then
after that point of change, some other code (probably the SIGINT handler
when you type Ctrl-C) does a longjmp() to revert back to the shell
initialization point.  So the question becomes what do you want the code
to see after the longjmp() - the state of the variable when setjmp() was
originally called, or the state of the variable at the time when
longjmp() was called?  Marking the variable volatile tells the compiler
that you explicitly want the latter semantics; otherwise, you get
undefined behavior.  Reading 'man longjmp':

       The compiler may optimize variables into registers, and
longjmp()  may
       restore  the values of other registers in addition to the stack
pointer
       and program counter.  Consequently, the values of  automatic
variables
       are  unspecified after a call to longjmp() if they meet all the
follow‐
       ing criteria:

       ·  they are local to the function that made the corresponding
setjmp()
          call;

       ·  their   values  are  changed  between  the  calls  to
setjmp()  and
          longjmp(); and

       ·  they are not declared as volatile.

       Analogous remarks apply for siglongjmp().

Note that longjmp() is not a very common programming practice these
days, but it IS very common in shells.  You'll see LOTS of code in bash
that uses code that was very idiomatic 30 years ago, even if it is less
commonly needed nowadays.

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.           +1-919-301-3226
Virtualization:  qemu.org | libvirt.org

Attachment: signature.asc
Description: OpenPGP digital signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]