Created attachment 24850 [details] apr-1.3.9-assume-cloexec.patch apr_file_open currently uses O_CLOEXEC when opening file's to avoid race conditions with the classic behavior of then using fcntl() to set the FD_CLOEXEC flag. this is all find and dandy except that on newer operating systems, the two fcntl() calls are still made even if the open() function supports O_CLOEXEC. when doing something like `svn commit` on a large tree, these translates to a huge number of useless syscalls. this should be easy to avoid -- if we called open() with O_CLOEXEC, and the fcntl() get step shows that FD_CLOEXEC is already set, we cache the result in a local variable. then in all future steps, we check the cached value before doing any fcntl() syscalls. getting back to subversion, before my fix, a simple `svn st` looks something like this: ...... open(".svn/entries", O_RDONLY|O_CLOEXEC) = 3 fcntl(3, F_GETFD) = 0x1 (flags FD_CLOEXEC) fcntl(3, F_SETFD, FD_CLOEXEC) = 0 read(3, "10\n\ndir\n9382\nsvn://nwd2cvs1.corp"..., 80) = 80 close(3) = 0 open(".svn/entries", O_RDONLY|O_CLOEXEC) = 3 fcntl(3, F_GETFD) = 0x1 (flags FD_CLOEXEC) fcntl(3, F_SETFD, FD_CLOEXEC) = 0 read(3, "10\n\ndir\n9382\nsvn://nwd2cvs1.corp"..., 4096) = 1187 read(3, "", 4096) = 0 read(3, "", 4096) = 0 close(3) = 0 open("vendors/.svn/entries", O_RDONLY|O_CLOEXEC) = 3 fcntl(3, F_GETFD) = 0x1 (flags FD_CLOEXEC) fcntl(3, F_SETFD, FD_CLOEXEC) = 0 read(3, "10\n\ndir\n9382\nsvn://nwd2cvs1.corp"..., 80) = 80 close(3) = 0 ...... and after, we see: ...... open(".svn/entries", O_RDONLY|O_CLOEXEC) = 3 fcntl(3, F_GETFD) = 0x1 (flags FD_CLOEXEC) fcntl(3, F_SETFD, FD_CLOEXEC) = 0 read(3, "10\n\ndir\n9382\nsvn://nwd2cvs1.corp"..., 80) = 80 close(3) = 0 open(".svn/entries", O_RDONLY|O_CLOEXEC) = 3 read(3, "10\n\ndir\n9382\nsvn://nwd2cvs1.corp"..., 4096) = 1187 read(3, "", 4096) = 0 read(3, "", 4096) = 0 close(3) = 0 open("vendors/.svn/entries", O_RDONLY|O_CLOEXEC) = 3 read(3, "10\n\ndir\n9382\nsvn://nwd2cvs1.corp"..., 80) = 80 close(3) = 0 ...... when working on a repo with thousands of dirs/files, you can see how this easily makes a significant difference.
This wouldn't fail safe in the case where O_CLOEXEC was ignored (an earlier kernel). I've change the code to avoid the second fcntl call in r905040. Thanks for the report!
sorry, i dont understand ... the has_o_cloexec variable is only set to 1 if the fcntl() get operation after the open(O_CLOEXEC) shows that O_CLOEXEC has been applied. a running program wont be moved between systems on the fly.
please review my latest comments. apr is not as optimal as it could be here.
r1183698, r1183730, r1183732, will be in 1.4.6
Fixed in 1.4.6 and later releases