- on fork, you are by definition implicitly cooperating with the parent as you are the same software image as the parent; in the case of transitive forks you can be expected, I think, to continue cooperating.
- on exec, you move from implicit cooperation to the need for explicit cooperation, through some kind of interface contract; e.g., the BASH_XTRACEFD environment variable. It is incumbent upon you to hide the good silverware before making the exec transition, as exec is a trust boundary; like when you sell your house, you don't get to control what the new owner of the process does with it, except through kernel-enforced mechanisms like privileges and resource controls and so on.
(rm -f /run/lock/temp && exec 5<> /run/lock/temp && echo test123 > /run/lock/temp && perl -e 'system("bash -c \"cat /dev/fd/5\"")')
it needs to work fine, and this shouldn't require any particular cooperation between Perl and Bash.FDs need to be inherited correctly... just like environment variables already are.
[1] It's literally a small, trivial loop in the original Bourne shell source code. In modern shells job control and other niceties require additional bookkeeping, but those aren't necessarily implicated in your example. I don't have a URL at hand for that source file, but I did find it last year or the year before, so it shouldn't be too hard to find if you're curious.