Skip to content

[plugin, Android] terminal: quick fix#12384

Closed
ghost wants to merge 4 commits into
masterfrom
unknown repository
Closed

[plugin, Android] terminal: quick fix#12384
ghost wants to merge 4 commits into
masterfrom
unknown repository

Conversation

@ghost

@ghost ghost commented Aug 20, 2024

Copy link
Copy Markdown

Fix for #12375 (comment) .


This change is Reviewable

@ghost ghost added bug Plugin labels Aug 20, 2024
@ghost ghost marked this pull request as draft August 20, 2024 07:06
@benoit-pierre

Copy link
Copy Markdown
Member

My tentative patch:

--- a/platform/android/luajit-launcher/assets/android.lua
+++ w/platform/android/luajit-launcher/assets/android.lua
@@ -2642,13 +2642,7 @@ local function run(android_app_state)
 
     os.execute = function(command) -- luacheck: ignore 122
         if command == nil then return -1 end
-        local argv = {}
-        command:gsub("([^ ]+)", function(arg)
-            -- strip quotes around argument, since they are not necessary here
-            arg = arg:gsub('"(.*)"', "%1") -- strip double quotes
-            arg = arg:gsub("'(.*)'", "%1") -- strip single quotes
-            table.insert(argv, arg)
-        end)
+        local argv = {'sh', '-c', command}
         return android.execute(unpack(argv))
     end
--- a/plugins/terminal.koplugin/main.lua
+++ b/plugins/terminal.koplugin/main.lua
@@ -93,29 +93,35 @@ local Terminal = WidgetContainer:extend{
 }
 
 function Terminal:isExecutable(file)
-    if os.execute(string.format("test -x %s", file)) == 0 then -- full path
-        return true
-    elseif os.execute(string.format("which %s 2>/dev/null 1>/dev/null", file)) == 0 then
-        return true
-    end
+    -- check if file is an executable or a command in PATH
+    return os.execute(string.format("test -x %s || command -v %s", file, file)) == 0
 end
 
 -- Try SHELL environment variable and some standard shells
 function Terminal:getDefaultShellExecutable()
     if self.default_shell_executable then return self.default_shell_executable end
 
-    local shell = {"mksh", "ksh", "zsh", "ash", "dash", "sh", "bash"}
-    table.insert(shell, os.getenv("SHELL"))
+    local shell = {
+        -- os.getenv("SHELL"),
+        "pouet",
+        "bash",
+        "sh",
+        "dash",
+        "ash",
+        "zsh",
+        "ksh",
+        "mksh",
+    }
 
-    while #shell >= 1  do
-        if self:isExecutable(shell[#shell]) then
-            self.default_shell_executable = shell[#shell]
+    for i, file in ipairs(shell) do
+        if self:isExecutable(file) then
+            self.default_shell_executable = file
             break
-        else
-            shell[#shell] = nil
         end
     end
 
+    logger.info('Terminal:default shell', self.default_shell_executable)
+
     return self.default_shell_executable
 end
 

@benoit-pierre

Copy link
Copy Markdown
Member

I am not quite fond with your patch

1. it calls the 'test -x' command with `sh -c`. (This could be done easier)

If our os.execute implementation for android is to be compatible with all current use cases, that's the only way (e.g. when using cmd … >redirection).

2. it depends on the shell built in `command`.

It's a POSIX shell builtin, so any compatible shell must support it.

The getDefaultShellExecutable method looks good.

Another thing that does not really make sense to me: sh in the middle of the list, which platform is going to have dash, or zsh, but not sh?

Also, I forgot to uncomment the os.getenv("SHELL") option, and to remove my pouet test. :P

@Frenzie

Frenzie commented Aug 20, 2024

Copy link
Copy Markdown
Member

ipairs will stop at the first entry if $SHELL is undefined (nil). Though it occurs to me the current code may have a similar issue since string.format will balk on nil.The current code doesn't have such an issue because table.insert(t, nil) at the end does nothing.

The most straightforward solution is probably

    local shell = {
        os.getenv("SHELL") or "",


if file ~= "" and self:isExecutable(file) then

but there might be a more elegant solution.

Edit: the current code is the more elegant solution.

@ghost ghost marked this pull request as ready for review August 20, 2024 14:35
@ghost

ghost commented Aug 20, 2024

Copy link
Copy Markdown
Author

So this works on the emulator, a Kobo Sage and a Android Pixel (Android S).

Comment thread plugins/terminal.koplugin/main.lua Outdated

if not self:isExecutable(shell) then
UIManager:show(InfoMessage:new{
text = -("Shell is not executable"),

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo

Suggested change
text = -("Shell is not executable"),
text = _("Shell is not executable"),

Comment thread plugins/terminal.koplugin/main.lua Outdated
end
else
UIManager:show(InfoMessage:new{
text = _("Shell not executable"),

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This text should be identical to the other Shell is not executable

@ghost

ghost commented Aug 20, 2024

Copy link
Copy Markdown
Author

ping @benoit-pierre Does this PR fix your issue on Marshmallow?

@benoit-pierre

Copy link
Copy Markdown
Member

No, still the same issue:

19:27:32.229  2785:2799       ProcessManager  W  waitpid on failed exec failed: No child processes
19:27:32.231  2785:2799                  art  F  art/runtime/java_vm_ext.cc:410] JNI DETECTED ERROR IN APPLICATION: JNI GetObjectClass called with pending exception java.io.IOException: Error running exec(). Command: [test, -x, bash] Working Directory: null Environment: null

@ghost

ghost commented Aug 20, 2024

Copy link
Copy Markdown
Author

Thanks, I will look into that tomorrow.
I feel (but have not found any docu on that), that bionic fork does something with the environment of the forked process.

@ghost

ghost commented Aug 20, 2024

Copy link
Copy Markdown
Author

No, still the same issue:

19:27:32.229  2785:2799       ProcessManager  W  waitpid on failed exec failed: No child processes
19:27:32.231  2785:2799                  art  F  art/runtime/java_vm_ext.cc:410] JNI DETECTED ERROR IN APPLICATION: JNI GetObjectClass called with pending exception java.io.IOException: Error running exec(). Command: [test, -x, bash] Working Directory: null Environment: null

Btw could you Post a langer Part of the crash.log, pleas?

@benoit-pierre

Copy link
Copy Markdown
Member

Here's the full log.

@ghost

ghost commented Aug 22, 2024

Copy link
Copy Markdown
Author

Thanks @benoit-pierre ;
You were almost right with your changed os.execute (mind the additional exit $?, to get the exit value of the command and not of the shell there).

It might be the main cause, that android does not have a system shell running -> os.execute() returns nil.

Before changing luajit-launcher, could you please test, if it works on Marshmallow now?

@benoit-pierre benoit-pierre left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll test it later tonight.

-- This should be moved inside `platform/android/luajit-launcher/assets/android.lua`
-- once we now it works as expected
if Device:isAndroid() and not os.getenv("SHELL") and os.execute() == nil then
local dummy, android = pcall(require, "android")

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
local dummy, android = pcall(require, "android")
local android = require("android")

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just die testing

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In which case? What's the error?

if Device:isAndroid() and not os.getenv("SHELL") and os.execute() == nil then
local dummy, android = pcall(require, "android")
os.execute = function(command) -- luacheck: ignore 122
command = command .. "; exit $?"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The exit code from the shell is already the code from the last command.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In which case is this not true?

@NiLuJe NiLuJe Sep 12, 2024

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The exit code from the shell is already the code from the last command.

Yup:

The equivalent of a bare exit is exit $? or even just omitting the exit.

(c.f., https://tldp.org/LDP/abs/html/exit-status.html#AEN2981)

Granted, this is Bash, but I assume this is the standard POSIX behavior. Anything else would be utter madness.

(A quick glance at toybox/busybox sh seems to confirm that).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Android doesn't care about standard POSIX behavior. Hard to imagine it wouldn't do the exit status in a semi-normal manner though.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://android.googlesource.com/platform/system/core/+/master/shell_and_utilities/README.md says

Since IceCreamSandwich Android has used mksh as its shell. Before then it used ash (which actually remained unused in the tree up to and including KitKat).

Hard to imagine a Korn shell from a BSD distro fucking up that bad either ;).


-- This should be moved inside `platform/android/luajit-launcher/assets/android.lua`
-- once we now it works as expected
if Device:isAndroid() and not os.getenv("SHELL") and os.execute() == nil then

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It still does not make sense to me to do it conditionally and end up with different implementation with completely different behaviors, one of them incompatible with how os.execute is supposed to work (again, supporting cmd … >redirect, like on other platforms).

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This ia test Here, as i dont want to Change luajit right now. If we know it Works now, this pice of Code should be in Android lua. Bit this is in a different subproject

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So once moved to android.lua, that variant of the function is always going to be used? No not os.getenv("SHELL") and os.execute() == nil conditional?

For testing, why not just use if Device:isAndroid() then?

@ghost

ghost commented Aug 22, 2024

Copy link
Copy Markdown
Author

@benoit-pierre So much questions! I Just politely asked If this Works ... I expected an answer

@poire-z poire-z mentioned this pull request Aug 25, 2024
@ghost ghost closed this by deleting the head repository Sep 27, 2024
NiLuJe pushed a commit to NiLuJe/koreader that referenced this pull request Oct 12, 2024
NiLuJe pushed a commit to NiLuJe/koreader that referenced this pull request Oct 12, 2024
NiLuJe pushed a commit to NiLuJe/koreader that referenced this pull request Oct 12, 2024
NiLuJe pushed a commit to NiLuJe/koreader that referenced this pull request Oct 12, 2024
NiLuJe pushed a commit that referenced this pull request Oct 13, 2024
NiLuJe pushed a commit that referenced this pull request Oct 13, 2024
0xstillb pushed a commit to 0xstillb/koreader-thai that referenced this pull request May 9, 2026
0xstillb pushed a commit to 0xstillb/koreader-thai that referenced this pull request May 9, 2026
This pull request was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants