-
Notifications
You must be signed in to change notification settings - Fork 292
Unifying chunk buffer size logic #144
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
base: master
Are you sure you want to change the base?
Conversation
Please provide some more details about "what" is 4k and "when" this scenario occurs so that I can try to reproduce it. Also, please share your config settings, most importantly whether you have set A suboptimal allocation strategy in some cases is one thing to look at. I have a hunch that neither is true in the way you have presented and that your system is memory constrained. Depending on the configuration settings of |
[1] To make sure things before startBefore answering what you ask, I confirm what we are confused First, the issue of failing fork happened on 1.4.52 version which is very old version. Second, there wasn't server.chunkqueue-chunk-sz field in lighttpd.conf. [2] Code reviewBack to what you ask, I will show you the logic which cuase failing fork on 1.4.52
Focusing on chunkqueue_append_buffer_open_sz,
And Here's the problem, if required size (size_sz) was 4096 Jumping into chunkqueue_buffer_open_resize,
the previous chunk size is also same as chunk_buf_sz. So it keep holding 4KB memory in chunk list rather than releasing memory actually. In my case, the issue happened when trying to send a file larger than 30 MB through lighttpd. How it could be resolved in 1.4.55 version
Rather than that, [3] Why I pull request on 1.4.82 versionFinally, I think you will wonder then why I pull request even the issue doesn't happen again by updating to 1.4.55. 1.4.55 version (resolved 1.4.52 version issue)
1.4.82 version (latest version)
As you can see, you change the first conditional statements If so, then I think you should also change sz = (sz + (chunk_buf_sz-1)) & ~(chunk_buf_sz-1) to If not changing like what I recommend, you could avoid excess allocation just only if required memory is chunk_buf_sz+ 1. So changing to chunk_init_sz(((sz&~1uL)+(chunk_buf_sz-1)) & ~(chunk_buf_sz-1)); will ensure that every (chunk_buf_sz * N) + 1 become (chunk_buf_sz * N) But instead of that, I suggest revert it to 1.4.55 version.Based on 1.4.55 version, when (chunk_buf_sz * N) + 1 size is required, then it return (chunk_buf_sz * N) + 1. On the 1.4.52 version, on the other hand, it always ensure extra space for '/0' regardless of required size. Thank you |
lighttpd 1.4.52 was released Nov 2018, approaching 7 years ago. I hope that you realize that while your ability to troubleshoot this is commendable, it is unfortunately negated by your oversight in not first testing to see if newer versions of lighttpd addressed have better optimizations. Issues such as https://redmine.lighttpd.net/issues/3033 were identified and fixed many years ago, but after lighttpd 1.4.55.
Why should I care? lighttpd 1.4.55 is over 5 years ago. You seem to have neglected sharing an explanation of why you are incapable of using modern versions of lighttpd. |
please read part 3 |
Sorry. I was trying to answer quickly. I'll re-read in a few weeks. I am unable to give this further attention at this time. Aside: it does not look good for you to keep misspelling the name of the variable |
Okay, thank you for quick replying and feedback. |
Hi, I'm an engineer who use your lighttpd1.4
It would not be a bug on your side. But based on my experience, I think it can cause critical issue.
[1] Issue in the original code
1
Oversized buffer size logic is different between chunk_buffer_acquire_sz() and chunk_acquire().
2
According to chunk_acquire()
Every number of sz become size up to the nearest multiple number of chunk_buf_sz.
But only when sz is 8193, it size down to the nearest multiple number of chunk_buf_sz 8192.
[2] What I fix
I unify all the rule of sizing chunk buffer as sizing up to the nearest multiple number of chunk_buf_sz.
I know you try to avoid excess allocation by sizing down sz when sz is chunk_buf_sz*N+1
I explain below why I fixed it this way.
[3] Why I do this
1
Until recently, I use lighttpd 1.4.52 which is 7 years ago version.
With this version when ethernet speed is over 1Gbps, lighttpd fail to fork because of lack of memory.
I found out chunkqueue_append_buffer_open_sz() in chunk.c was related with it
It allocated new memory whenever sz is 4KB and sz is always 4KB when using 1Gbps ethernet.
So it caused memory leak.
I know it's not directly related with this issue, but these two issue are related with allocating additional space for '\0'
So it would be better to give additional space for '\0' regardless of the size of sz.
2
As I understand, it doesn't give extra space for '\0' when sz is chunk_buf_sz*N+1.
But it allocate extra space if sz is not chunk_buf_sz*N+1. So I think it lose some consistency.
Thank you