how to implement safe version of $(shell) without .NOTPARALLEL ?

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

how to implement safe version of $(shell) without .NOTPARALLEL ?

Britton Kerin
I currently have this:

SHELL_CHECKED =                                                      \
  $(strip                                                            \
    $(if $(shell (($1) 1>/tmp/SC_so) || echo nonempty),              \
      $(error shell command '$1' failed.  Its stderr should be above \
              somewhere.  Its stdout is in '/tmp/SC_so'),            \
      $(shell cat /tmp/SC_so && rm -f /tmp/SC_so)))

Calls can safely be nested but not run in parallel.  I could use flock
(linux-only-ish) or mkdir trick (painful) or parallel --semaphore
(needs GNU parallel) but any of those would break nesting anyway.  I
guess a stack or something could be used but I'd like to avoid getting
that crazy.
Is there some way I'm missing?

It looks like checking $(.SHELLSTATUS) after might also involve a race?

It seems to me that a checked version of $(shell) would be a nice
feature to ship with Make since it's commonly wanted and  looks much
easier to implement inside make than outside it.

Britton

_______________________________________________
Help-make mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/help-make
Reply | Threaded
Open this post in threaded view
|

Re: how to implement safe version of $(shell) without .NOTPARALLEL ?

Paul Smith-20
On Sun, 2019-03-17 at 05:57 -0800, Britton Kerin wrote:
> SHELL_CHECKED =                                                      \
>   $(strip                                                            \
>     $(if $(shell (($1) 1>/tmp/SC_so) || echo nonempty),              \
>       $(error shell command '$1' failed.  Its stderr should be above \
>               somewhere.  Its stdout is in '/tmp/SC_so'),            \
>       $(shell cat /tmp/SC_so && rm -f /tmp/SC_so)))
>
> Calls can safely be nested but not run in parallel.

Can you show how you're trying to use this?  I have to assume that
you're trying to use this variable within a recipe.

It's an antipattern to use $(shell ...) inside a recipe; it was not
designed to be used there (since a recipe is already running in a shell
there's little reason to do so) and there are many issues with it.

I recommend using real shell commands in your SHELL_CHECKED variable,
rather than using make functions.  That will solve your problem with
status checking.

As for locking, I recommend writing to a unique file for each instance:
maybe using the $$ value to get the current shell's PID--of course in
makefiles you have to write it as $$$$ instead.


_______________________________________________
Help-make mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/help-make