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

Server gets stuck in a read loop when trying to upload a file named testmgr.c #495

Open
Fornax96 opened this issue Nov 14, 2024 · 3 comments

Comments

@Fornax96
Copy link

Fornax96 commented Nov 14, 2024

Hi, I have a very weird problem. I noticed that sometimes my server would get stuck in a tight loop, burning 100% CPU. I finally found out what causes it.

I was uploading the linux kernel sources for testing and one particular file would cause the loop to happen: testmgr.c. I tried renaming the file, that fixes the issue. I also tried naming a different file to testmgr.c, that also causes the loop to happen. It doesn't matter what the contents of the file are, it also doesn't matter in which directory the file is stored. The problem triggers for all files with the name testmgr.c. There are probably other names which cause the issue to happen as well.

Here is exactly what I've observed:

  • The FTP driver calls the OpenFile method of my Afero FS with these params: name: /linux-6.11.8/crypto/testmgr.c, flag: 577, mode: -rwxrwxrwx
  • A writable file is returned from my Afero FS.
  • ftpserverlib uses ReadFrom(io.Reader) to try to write to the file.
  • My code reads from the reader which was passed to ReadFrom, but the Read(buf) function keeps returning 0 bytes and no error every time. I had to add a limit to the number of read calls to break the loop. Without the failsave it would keep reading 0 bytes forever.

Here is the code I'm using to break the loop:

var nn int
for n < len(buf) && err == nil {
	nn, err = r.Read(buf[n:])
	n += nn

	if nn == 0 && err == nil {
		loops++
		if loops >= 100 {
			log.Warn("readFull: Nothing was read, but there was no error either. Returning ErrUnexpectedEOF break the loop")
			return n, io.ErrUnexpectedEOF
		}
	} else {
		loops = 0
	}
}

Thank you.

EDIT: It also happens with files called maple.c, nls_cp949.c

@drakkan
Copy link
Collaborator

drakkan commented Nov 15, 2024

Hi,

thanks for reporting this issue. Can you please try to replicate the same with some established software that uses this library like ftpserver or SFTPGo? Thank you

@Fornax96
Copy link
Author

Your FTP server does not seem to have this issue.

A thought occurred to me: It could be a bug in the ReadFrom() usage. I disabled ReadFrom on my implementation and the transfer worked just fine. I'm going to look for the place where ftpserverlib uses ReadFrom to see if I can spot any problems.

@Fornax96
Copy link
Author

I can't figure out what the file name has to do with anything.. But when I try it the bug only occurs for those specific file names. Crazy. It's not a problem with my filesystem either, because when I try to upload the same file with HTTP it works fine, and that uses the same interface on the backend.

I installed logging to see what the reader returns, and it's only a few bytes per read. Usually between 10 and 50 bytes. My writer interface needs chunks of exactly 512 kiB to work. So I think the problem here is that both the reader and writer are not willing to let go of their alignment. I'll have to install some buffering inbetween.

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

No branches or pull requests

2 participants