[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
signature.asc
Description: OpenPGP digital signature