On Mon, Oct 17, 2016 at 08:38:29PM +0200, Martijn Dekker wrote: [...] The BASHPID variable is initialized with null_assign as its "assign_func". The default value for this attribute in newly created variables is NULL.
The problem here is caused by the following code from variables.c (function is bind_variable_internal): 2753 else if (entry->assign_func) /* array vars have assign functions now */ 2754 { 2755 INVALIDATE_EXPORTSTR (entry); 2756 newval = (aflags & ASS_APPEND) ? make_variable_value (entry, value, aflags) : value; 2757 if (assoc_p (entry)) 2758 entry = (*(entry->assign_func)) (entry, newval, -1, savestring ("0")); 2759 else if (array_p (entry)) 2760 entry = (*(entry->assign_func)) (entry, newval, 0, 0); 2761 else 2762 entry = (*(entry->assign_func)) (entry, newval, -1, 0); 2763 if (newval != value) 2764 free (newval); 2765 return (entry); 2766 } 2767 else 2768 { 2769 assign_value: 2770 if ((readonly_p (entry) && (aflags & ASS_FORCE) == 0) || noassign_p (entry)) 2771 { 2772 if (readonly_p (entry)) 2773 err_readonly (name_cell (entry)); 2774 return (entry); 2775 } 2776 2777 /* Variables which are bound are visible. */ 2778 VUNSETATTR (entry, att_invisible); If a variable has a non-NULL assign_func, it will not run the readonly_p (entry) check, and therefore, no error message is printed. I'm not sure why the code exits, but it seems clear to me that the assign_func should be NULL in this case. I attach a patch with the "fix" (disclaimer, I'm not sure this is the proper fix, that's for Chet to decide). Patched bash: dualbus@yaqui:~/local/src/gnu/bash$ ./bash -c 'BASHPID=1; echo $?' ./bash: BASHPID: readonly variable -- Eduardo Bustamante https://dualbus.me/
diff --git a/variables.c b/variables.c index 2e8b38c..8cd5f58 100644 --- a/variables.c +++ b/variables.c @@ -1766,7 +1766,7 @@ initialize_dynamic_variables () INIT_DYNAMIC_VAR ("LINENO", (char *)NULL, get_lineno, assign_lineno); VSETATTR (v, att_integer); - INIT_DYNAMIC_VAR ("BASHPID", (char *)NULL, get_bashpid, null_assign); + INIT_DYNAMIC_VAR ("BASHPID", (char *)NULL, get_bashpid, (sh_var_assign_func_t *)NULL); VSETATTR (v, att_integer|att_readonly); #if defined (HISTORY)