1 # -*- encoding: binary -*-
7 append_flags = File::WRONLY | File::APPEND
12 (fp.fcntl(Fcntl::F_GETFL) & append_flags) == append_flags
13 rescue IOError, Errno::EBADF
17 def self.chown_logs(uid, gid)
18 ObjectSpace.each_object(File) do |fp|
19 fp.chown(uid, gid) if is_log?(fp)
24 # This reopens ALL logfiles in the process that have been rotated
25 # using logrotate(8) (without copytruncate) or similar tools.
26 # A +File+ object is considered for reopening if it is:
27 # 1) opened with the O_APPEND and O_WRONLY flags
28 # 2) the current open file handle does not match its original open path
29 # 3) unbuffered (as far as userspace buffering goes, not O_SYNC)
30 # Returns the number of files reopened
32 # In Unicorn 3.5.x and earlier, files must be opened with an absolute
33 # path to be considered a log file.
37 ObjectSpace.each_object(File) { |fp| is_log?(fp) and to_reopen << fp }
39 to_reopen.each do |fp|
42 rescue IOError, Errno::EBADF # race
47 b = File.stat(fp.path)
48 next if orig_st.ino == b.ino && orig_st.dev == b.dev
53 # stdin, stdout, stderr are special. The following dance should
54 # guarantee there is no window where `fp' is unwritable in MRI
55 # (or any correct Ruby implementation).
57 # Fwiw, GVL has zero bearing here. This is tricky because of
58 # the unavoidable existence of stdio FILE * pointers for
59 # std{in,out,err} in all programs which may use the standard C library
61 # We do not want to hit fclose(3)->dup(2) window for std{in,out,err}
62 # MRI will use freopen(3) here internally on std{in,out,err}
63 fp.reopen(fp.path, "a")
65 # We should not need this workaround, Ruby can be fixed:
66 # http://bugs.ruby-lang.org/issues/9036
67 # MRI will not call call fclose(3) or freopen(3) here
68 # since there's no associated std{in,out,err} FILE * pointer
69 # This should atomically use dup3(2) (or dup2(2)) syscall
70 File.open(fp.path, "a") { |tmpfp| fp.reopen(tmpfp) }
74 fp.flush # IO#sync=true may not implicitly flush
77 # this should only happen in the master:
78 if orig_st.uid != new_st.uid || orig_st.gid != new_st.gid
79 fp.chown(orig_st.uid, orig_st.gid)
83 rescue IOError, Errno::EBADF
84 # not much we can do...