Skip to content

FFM implementation returns -1 when using reader().read(timeout) (MacOS M3 related?)Β #1879

Closed

Description

@bitspittle

I've attached a minimal repro project to showcase what I'm running into.

jline-ffm-read-eof.zip

The README from said project:


This project showcases (I think?) a bug with the FFM terminal representation when trying to call
terminal.reader().read(timeout)

Repro steps

This project uses JDK25 (via Gradle toolchain) and has a dependency on jline 4.1.0 (see gradle/libs.versions.toml).
Probably earlier JDKs might also work, but my understanding is JDK25 is the first version that FFM is really mature.

In case it matters, my machine is an M3 MacBook Pro. (uname -m βž” arm64)

This project has only a single code file in it: src/main/kotlin/main.kt

  • Unzip the attached project into a location of your preference. It will pull out a folder called jline-ffm-read-eof so you don't have to worry about files exploding all over your current directory like a mess.
  • In a terminal....
  • Make sure you have JDK25 or newer installed (java -version)
  • cd into this project's root
  • ./gradlew installDist
  • ./build/install/jline-ffm-read-eof/bin/jline-ffm-read-eof

The program should immediately print out the line: Terminal class: org.jline.terminal.impl.ffm.FfmUnixSysTerminal

Expected behavior

Then, as a user, you should just be able to press keys, e.g. press "q" and the terminal will say: "Read: 113"

Actual behavior

The program exits immediately before I get a chance to type, printing: "Got EOF (-1), exiting"

Additionally, if you change main.kt to look like this:

// Before
if (c >= 0) {
    println("Read: $c")
}
if (c == -1) {
    println("Got EOF (-1), exiting")
    quit = true
}

// After
if (c >= -1) {
   println("Read: $c")
}

you will see that the FFM implementation does read keypresses, but it also spits out -1's at a regular cadence.
Here is the output I got when typing "Hello":

Terminal class: org.jline.terminal.impl.ffm.FfmUnixSysTerminal
Read: -1
Read: -1
Read: -1
Read: -1
Read: -1
Read: -1
Read: 104
Read: -1
Read: -1
Read: 101
Read: -1
Read: 108
Read: -1
Read: 108
Read: -1
Read: -1
Read: 111
Read: -1
Read: -1
Read: -1
Read: -1
Read: -1

My understanding

I'll write out my assumptions, just in case this bug is really just user error.

When calling reader().read(...), essentially, this value should either return:

  • a real character code value (a user just pressed a key)
  • -2 if the read call timed out (which is fine, just ignore it)
  • -1 to indicate the input stream ended (e.g. user pressed ctrl+D), which means you should quit the loop

In other words:

var quit = false
while (!quit) {
    val c = terminal.reader().read(16)
    if (c >= 0) {
        // Valid character received. Process it!
    } else if (c == -1) {
        quit = true
    }
}

I've been using Jline for years and this has worked fine for me using the Exec fallback.

But with FFM, it seems to sporadically give me -1's, which kills my while loop almost immediately.

I assume this is a bug. It may also be related to my OS, I'm not sure.

Hopefully the team will be able to reproduce this issue on their end.

Activity

  1. bitspittle commented on May 14, 2026

    @bitspittle
    Author

    Also this might be interesting? I tried using versions 4.0.0 through 4.0.15, and in those cases, the FFM dependency didn't pick up at all, and I kept getting set to the system exec fallback (org.jline.terminal.impl.PosixSysTerminal). So something major changed in 4.1.0 for me.

    Also also: I am not getting the jni dependency to work on this machine. I always end up falling back to posix sys terminal implementation in that case as well. You can go into libs.versions.toml and comment out the ffm declaration on line 22 which means you should now be trying to load the jni provider. Check to see if you're actually getting that or, like me, are getting the fallback implementation instead.

  2. changed the title [-]FFM implementation returns -1 when using `reader().read(timeout)`[/-] [+]FFM implementation returns -1 when using `reader().read(timeout)` (MacOS M3 related?)[/+] on May 15, 2026
  3. added a commit that references this issue on May 23, 2026
    6ac5ec1
  4. bitspittle commented on May 23, 2026

    @bitspittle
    Author

    Oh wow thanks for the quick fix. I'll try updating to 4.1.2 when I get a chance and confirm. It may be a few days.

  5. added 4 commits that reference this issue on Jun 16, 2026
    f4c754e
    414848f
    5aebb06
    f733381
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions