-
Type:
Bug
-
Resolution: Unresolved
-
Priority:
Major
-
Component/s: durable-task-plugin
-
None
Hi,
When migrating our docker agent image from a RHEL 9 using JDK 22 or 23 to a RHEL 10 image using JDK 21 we have found a regression for some `sh` invocation that may hang forever. Basically, we have one shell script called by `sh` which eventually calls something like:
```
RANDOM_STRING="$(tr -dc 'a-z0-9' < /dev/urandom | fold -w 4 | head -n1)"
```
This works only if SIGPIPE isn't blocked, as we definitely expect the `head` command to immediately send a SIGPIPE to the `fold` command after one line as been echoed. If you run this in a "normal" shell, it works fine, however if you run this with SIGPIPE ignored, then you will see it hang for ever. On a recent distro, you can emulate this way:
```
[amadeus@50ca067559e9]~% env --ignore-signal=SIGPIPE sh -c "tr -dc 'a-z0-9' < /dev/urandom | fold -w 4 | head -n1"
aa78
^C <--- here it hangs for ever until hitting control + C
```
It happens that some java implementation do hide the SIGPIPE signal by default. This is the case of the JDK 21 found on RHEL 9/10/Fedora. You can easily reproduce that in some docker images based on CentOS/Fedora and run this trivial java program that is just a wrapper for system commands passed as argument:
```
[amadeus@50ca067559e9]~% cat plop.java
import java.io.BufferedReader; Â Â
import java.io.InputStreamReader;
import java.io.IOException;
class TestSystemCommand
{
  public static void main(String[] args)
  {
    try
    {
      Process process = Runtime.getRuntime().exec(args);
      BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
      String line;
      while ((line = reader.readLine()) != null)
     Â
      reader.close();
    }
    catch (IOException e)
   Â
  }
}
```
Which you can run like this:
```
[amadeus@50ca067559e9]~% java plop.java sh -c "tr -dc 'a-z0-9' < /dev/urandom | fold -w 4 | head -n1"
7ow9
^C%Â <--- Hang for ever until hitting control + C
```
If you run a `quay.io/fedora/fedora` container and `dnf install -y java-latest-openjdk-headless java-21-openjdk-headless` then you can see that there is at least with openjdk some difference of behavior between JDK 21 and JDK 24:
```
[root@3711488feefd /]# /usr/lib/jvm/java-21-openjdk/bin/java plop.java sh -c "tr -dc 'a-z0-9' < /dev/urandom | fold -w 4 | head -n1"
5eco
^C[root@3711488feefd /]#Â <--- Hangs for ever here
[root@3711488feefd /]# /usr/lib/jvm/java-24-openjdk/bin/java plop.java sh -c "tr -dc 'a-z0-9' < /dev/urandom | fold -w 4 | head -n1"
o8qn
[root@3711488feefd /]#
```
When using a recent coreutils (coreutils >= 8.31, released in 2019), this issue can be fixed by wrapping the command with the `env` command like this:
```
[root@3711488feefd /]# /usr/lib/jvm/java-21-openjdk/bin/java plop.java env --default-signal=SIGPIPE sh -c "tr -dc 'a-z0-9' < /dev/urandom | fold -w 4 | head -n1"
x0jw
[root@3711488feefd /]# /usr/lib/jvm/java-24-openjdk/bin/java plop.java env --default-signal=SIGPIPE sh -c "tr -dc 'a-z0-9' < /dev/urandom | fold -w 4 | head -n1"
s864
```
In order to cope with both old and new OS, where `env` might know the `--default-signal` argument, this more complex wrapper can be used:
```
[root@3711488feefd /]# /usr/lib/jvm/java-21-openjdk/bin/java plop.java sh -c 'if env --default-signal=SIGPIPE true 1>/dev/null 2>&1; then exec env --default-signal=SIGPIPE "$@"; else exec "$@"; fi' – sh -c "tr -dc 'a-z0-9' < /dev/urandom | fold -w 4 | head -n1"Â
n3d7
[root@3711488feefd /]# /usr/lib/jvm/java-24-openjdk/bin/java plop.java sh -c 'if env --default-signal=SIGPIPE true 1>/dev/null 2>&1; then exec env --default-signal=SIGPIPE "$@"; else exec "$@"; fi' – sh -c "tr -dc 'a-z0-9' < /dev/urandom | fold -w 4 | head -n1"Â
ormg
```
I will submit a pull request in the Github repo to wrap the call to `nohup` with the above described workaround.
Cheers,
Romain