Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: implement io.popen #88

Merged
merged 21 commits into from
Jan 8, 2023
Merged

feat: implement io.popen #88

merged 21 commits into from
Jan 8, 2023

Conversation

TorchedSammy
Copy link
Contributor

@TorchedSammy TorchedSammy commented May 25, 2022

as of writing, the pr only adds the popen function; iolib.File is untouched.
is there anything else i need to add here, like tests? also how should i actually handle file options, or is it fine as-is?

closes #7

Copy link
Owner

@arnodel arnodel left a comment

Choose a reason for hiding this comment

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

That seems almost it. Apart from the mode validation I think there is another issue to figure out: what happens when the file is closed? A simple test in lua 5.4 gives this:

> f = io.popen("echo foo")
> f
file (0x21021ac10)
> f:close()
true	exit	0
> f
file (closed)

What happens in Golua? Given there is no real file handle backing up the File instance I think things may go wrong here.

A few tests would be good also, best if they could be cross-platform.

lib/iolib/iolib.go Show resolved Hide resolved
@codecov
Copy link

codecov bot commented May 26, 2022

Codecov Report

Base: 89.05% // Head: 88.82% // Decreases project coverage by -0.23% ⚠️

Coverage data is based on head (cd624ec) compared to base (4f77264).
Patch coverage: 67.52% of modified lines in pull request are covered.

Additional details and impacted files
@@            Coverage Diff             @@
##           lua5.4      #88      +/-   ##
==========================================
- Coverage   89.05%   88.82%   -0.24%     
==========================================
  Files         104      104              
  Lines       11122    11233     +111     
==========================================
+ Hits         9905     9978      +73     
- Misses        921      949      +28     
- Partials      296      306      +10     
Impacted Files Coverage Δ
lib/iolib/file.go 80.17% <66.66%> (-1.31%) ⬇️
lib/iolib/iolib.go 87.42% <67.64%> (-5.00%) ⬇️

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.

☔ View full report at Codecov.
📢 Do you have feedback about the report comment? Let us know in this issue.

@TorchedSammy
Copy link
Contributor Author

an idea for handling file operations on popen is that i could add the cmd to iolib.File and add specific functions for that. what do you think?

also how do i improve coverage... by writing the lua tests?

@arnodel
Copy link
Owner

arnodel commented May 26, 2022

an idea for handling file operations on popen is that i could add the cmd to iolib.File and add specific functions for that. what do you think?

It depends on the behaviour that popen implements I think. It's not really specified in the Lua docs afaict so it might be a matter of testing it in Lua (or looking at the code). Go's exec.Cmd.StdoutPipe() actually returns an io.ReadCloser instance so it might be enough to call Close() on that when closing the Lua file (simplest way might be to check if the the reader implements io.Closer when there is no file to close - and do it with the writer in the case we are writing into the process instead of reading from it). The problem is that I don't know if that leads to behaviour consistent with the C Lua implementation. It could be good enough as a first go anyway!

also how do i improve coverage... by writing the lua tests?

Yes :). I am not very familiar with windows but perhaps the windows shell implements echo and cat >file which would allow testing both reading from and writing to a process?

@TorchedSammy
Copy link
Contributor Author

Go's exec.Cmd.StdoutPipe() actually returns an io.ReadCloser instance so it might be enough to call Close() on that when closing the Lua file

close on popen returns the process' status (same returns as os.execute) so i don't think it'll be enough

@arnodel
Copy link
Owner

arnodel commented May 26, 2022

Go's exec.Cmd.StdoutPipe() actually returns an io.ReadCloser instance so it might be enough to call Close() on that when closing the Lua file

close on popen returns the process' status (same returns as os.execute) so i don't think it'll be enough

Yeah I just had a quick look at C Lua, Lua file objects contain a callback for closing the file. In the case of files opened by popen, the callback calls pclose(). I think the equivalent in Go is going to be to call reader.Close() (or writer.Close()) and then to do command.Wait(). You could copy the Lua approach and add a (optional?) callback to the File data structure that does closing.

@TorchedSammy
Copy link
Contributor Author

TorchedSammy commented May 26, 2022

there is another issue to figure out: what happens when the file is closed? [...]
Given there is no real file handle backing up the File instance I think things may go wrong here.

fixed. tested in hilbish

~/Files/Projects/Hilbish master*
∆ f = io.popen 'sleep 5' 
~/Files/Projects/Hilbish master*
∆ print(f:close())
true	exit	0
~/Files/Projects/Hilbish master*
∆ f = io.popen 'false'
~/Files/Projects/Hilbish master*
∆ print(f:close()) 
nil	exit	1
~/Files/Projects/Hilbish master*
∆ f = io.popen 'sleep 15'
~/Files/Projects/Hilbish master*
∆ print(f:close())
nil	signal	15

@TorchedSammy
Copy link
Contributor Author

now just the other functions, and tests

@TorchedSammy TorchedSammy requested a review from arnodel May 26, 2022 16:53
@TorchedSammy
Copy link
Contributor Author

TorchedSammy commented May 26, 2022

for tests i just copy pasted already available ones (but only 2 suites)
everything should be good now (except for setvbuf - not sure what to do with that)

@TorchedSammy
Copy link
Contributor Author

ok i'm not sure why tests are failing and how wait is blocking

@arnodel
Copy link
Owner

arnodel commented May 26, 2022

ok i'm not sure why tests are failing and how wait is blocking

I think the test

    local f = io.popen("cat files/iotest.txt")

should be

    local f = io.popen("cat files/iotest.txt", "w")

You want to write to the process, not read from it. I might have some time to look at it tomorrow.

@TorchedSammy
Copy link
Contributor Author

no it's the popen write test (local f = io.popen("cat > files/popenwrite.txt", "w"))
looks like gopher-lua has the same problem, but c lua doesn't

@arnodel
Copy link
Owner

arnodel commented May 27, 2022

no it's the popen write test (local f = io.popen("cat > files/popenwrite.txt", "w")) looks like gopher-lua has the same problem, but c lua doesn't

As a sanity check I wrote this little Go program:

func main() {
	cmd := exec.Command("/bin/sh", "-c", "cat > foo.txt")
	stdin, _ := cmd.StdinPipe()
	fmt.Println("Starting cat...")
	cmd.Start()
	go func() {
		fmt.Println("Sending greeting...")
		fmt.Fprintln(stdin, "Hello from test")
		fmt.Println("Waiting 5s...")
		time.Sleep(5 * time.Second)
		fmt.Println("Closing stdin...")
		stdin.Close()
	}()
	fmt.Println("Waiting for cat to exit...")
	cmd.Wait()
	fmt.Println("Done")
}

That terminates fine, and suggests that cmd.Wait() should not block provided the stdin pipe was closed previously. I probably don't have time today sadly.

@TorchedSammy
Copy link
Contributor Author

weirdly, not using a type assert and just storing the stdout/stdin pipe makes it work from my side. now we should be good

lib/iolib/lua/iolib.lua Outdated Show resolved Hide resolved
lib/iolib/file.go Outdated Show resolved Hide resolved
TorchedSammy and others added 2 commits May 28, 2022 13:52
Co-authored-by: Arnaud Delobelle <arnodel@gmail.com>
@TorchedSammy TorchedSammy requested a review from arnodel May 28, 2022 18:17
@TorchedSammy
Copy link
Contributor Author

anything else to fix/improve? i'm not sure how to improve the coverage; what else to test

@arnodel
Copy link
Owner

arnodel commented May 31, 2022

anything else to fix/improve? i'm not sure how to improve the coverage; what else to test

If you could just disable the failing test on windows, then I'll merge it. Don't worry about test coverage atm

@TorchedSammy
Copy link
Contributor Author

If you could just disable the failing test on windows,

oh how do i do that

@TorchedSammy
Copy link
Contributor Author

does that work?

@arnodel
Copy link
Owner

arnodel commented Jun 1, 2022

does that work?

Sadly that doesn't work because the expected results are not conditional. I should have some time tomorrow so hopefully I can figure out something to help with that.

@arnodel
Copy link
Owner

arnodel commented Jun 2, 2022

does that work?

Sadly that doesn't work because the expected results are not conditional. I should have some time tomorrow so hopefully I can figure out something to help with that.

I added a feature to help with this: 41f7e93

You should be able to put the tests that fail on windows in a file e.g. non_windows_popen.lua and set the first line to be

-- tags: !windows

It will only run this lua test file on non-windows platforms

HTH

Edit: this commit is on the default branch (lua5.4)

Edit 2: the working commit is 8cf7d84

@TorchedSammy
Copy link
Contributor Author

like that?

Copy link
Owner

@arnodel arnodel left a comment

Choose a reason for hiding this comment

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

Yes that looks good, thank you. Windows tests are still failing though (see comments). I do not have a windows environment to test in, so I don't have any suggestions why they are not working. If you can't debug the issue either and you don't need a windows implementation we could always disable popen on windows for now? I think it would be better than to have a broken implementation.

--> ~^false\t.*invalid format


for line in f:lines() do
Copy link
Owner

Choose a reason for hiding this comment

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

Looks like this is not finding any lines in windows (see e.g. test failure at https://github.com/arnodel/golua/runs/6722468583?check_suite_focus=true#step:4:35)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

how does that even make sense

@TorchedSammy
Copy link
Contributor Author

TorchedSammy commented Jun 4, 2022

i wanna have popen on windows at least, but this is infuriating

edit: i do have a windows install but it is excruciatingly slow and i would rather not use it

@arnodel
Copy link
Owner

arnodel commented Jun 6, 2022

i wanna have popen on windows at least, but this is infuriating

edit: i do have a windows install but it is excruciatingly slow and i would rather not use it

I can try to find a way forward, but it probably won't be very quick as it means getting a windows environment.

@TorchedSammy
Copy link
Contributor Author

TorchedSammy commented Jun 6, 2022

I can try to find a way forward, but it probably won't be very quick as it means getting a windows environment.

that's fine, i won't be able to do much because of school finals

@TorchedSammy
Copy link
Contributor Author

hello?

@arnodel
Copy link
Owner

arnodel commented Jun 22, 2022 via email

@arnodel
Copy link
Owner

arnodel commented Jul 11, 2022

Update: I only have an apple silicon mac at the moment and it appears to be tricky to run windows on it - so far no luck so I'll need to get another way to have access.

@TorchedSammy
Copy link
Contributor Author

been a while huh

i'm on windows myself now and it seems to actually be decent so i can try testing to fix the issue

@TorchedSammy
Copy link
Contributor Author

TorchedSammy commented Aug 17, 2022

the path needed a backward slash

yeah that makes sense
with that all the iolib tests pass so this can be merged !!
i'll make the fix later (i don't have my gpg key on windows)

@TorchedSammy
Copy link
Contributor Author

ya good? didnt want to poke, but it's been 4 months so whats happening

Copy link
Owner

@arnodel arnodel left a comment

Choose a reason for hiding this comment

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

The only change I would request before merging is to update the README.md file which currently marks popen as unimplemented.

@TorchedSammy
Copy link
Contributor Author

like that?

Copy link
Owner

@arnodel arnodel left a comment

Choose a reason for hiding this comment

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

It's going in

@arnodel arnodel merged commit 0e5b284 into arnodel:lua5.4 Jan 8, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Implement io.popen()
2 participants