From: Mikko Rasa Date: Sat, 2 Dec 2017 15:03:10 +0000 (+0200) Subject: Implement controls for file descriptor inheritance X-Git-Url: http://git.tdb.fi/?p=libs%2Fcore.git;a=commitdiff_plain;h=ea8bf8f588310b0d7fd3297d74907602705bba1d Implement controls for file descriptor inheritance --- diff --git a/source/core/unix/process.cpp b/source/core/unix/process.cpp index 76141b0..99be2e1 100644 --- a/source/core/unix/process.cpp +++ b/source/core/unix/process.cpp @@ -39,6 +39,7 @@ void Process::execute(const string &command, bool path_search, const Arguments & if(redirect) { + // dup2 clears O_CLOEXEC if(cin) IO::cin.redirect(*cin); if(cout) diff --git a/source/io/base.h b/source/io/base.h index 1fe143e..a6a8827 100644 --- a/source/io/base.h +++ b/source/io/base.h @@ -59,6 +59,12 @@ public: Blocking is enabled by default. */ virtual void set_block(bool) = 0; + /** Sets inheritance mode. When inheritance is enabled, the file descriptor + will persist through Process::execute. + + Inheritance is disabled by default. */ + virtual void set_inherit(bool) = 0; + /** Returns the current mode flags. */ Mode get_mode() const { return mode; } diff --git a/source/io/buffered.cpp b/source/io/buffered.cpp index 6567fff..2836e4b 100644 --- a/source/io/buffered.cpp +++ b/source/io/buffered.cpp @@ -37,6 +37,11 @@ void Buffered::set_block(bool) throw logic_error("Buffered::set_block"); } +void Buffered::set_inherit(bool) +{ + throw logic_error("Buffered::set_block"); +} + void Buffered::flush() { if(cur_op==M_WRITE) diff --git a/source/io/buffered.h b/source/io/buffered.h index c88f0f8..da917e0 100644 --- a/source/io/buffered.h +++ b/source/io/buffered.h @@ -22,6 +22,7 @@ public: ~Buffered(); virtual void set_block(bool); + virtual void set_inherit(bool); void flush(); diff --git a/source/io/console.cpp b/source/io/console.cpp index e70f31d..a7417ed 100644 --- a/source/io/console.cpp +++ b/source/io/console.cpp @@ -22,6 +22,12 @@ void Console::set_block(bool b) sys_set_blocking(handle, b); } +void Console::set_inherit(bool i) +{ + adjust_mode(mode, M_INHERIT, i); + sys_set_inherit(handle, i); +} + unsigned Console::do_write(const char *buf, unsigned len) { check_access(M_WRITE); diff --git a/source/io/console.h b/source/io/console.h index e2b5d53..8feccfd 100644 --- a/source/io/console.h +++ b/source/io/console.h @@ -32,6 +32,7 @@ public: ~Console(); virtual void set_block(bool); + virtual void set_inherit(bool); /** If local echo is enabled, characters will appear on the console as they are typed. Can only be used on an input Console. */ diff --git a/source/io/file.cpp b/source/io/file.cpp index ab957c9..74b9f9f 100644 --- a/source/io/file.cpp +++ b/source/io/file.cpp @@ -32,6 +32,12 @@ void File::set_block(bool b) sys_set_blocking(handle, b); } +void File::set_inherit(bool i) +{ + adjust_mode(mode, M_INHERIT, i); + sys_set_inherit(handle, i); +} + unsigned File::do_write(const char *buf, unsigned size) { check_access(M_WRITE); @@ -96,6 +102,11 @@ void BufferedFile::set_block(bool b) file.set_block(b); } +void BufferedFile::set_inherit(bool) +{ + throw logic_error("BufferedFile::set_inherit"); +} + unsigned BufferedFile::do_write(const char *buf, unsigned size) { unsigned ret = buffer.write(buf, size); diff --git a/source/io/file.h b/source/io/file.h index ececa8d..85075d0 100644 --- a/source/io/file.h +++ b/source/io/file.h @@ -58,6 +58,7 @@ public: virtual ~File(); virtual void set_block(bool); + virtual void set_inherit(bool); protected: virtual unsigned do_write(const char *, unsigned); @@ -93,6 +94,7 @@ public: BufferedFile(const std::string &, Mode = M_READ, File::CreateMode = File::C_OVERWRITE); virtual void set_block(bool); + virtual void set_inherit(bool); protected: virtual unsigned do_write(const char *, unsigned); diff --git a/source/io/handle.h b/source/io/handle.h index 8a9db50..4b311f5 100644 --- a/source/io/handle.h +++ b/source/io/handle.h @@ -29,6 +29,7 @@ public: void sys_set_blocking(Handle &, bool); +void sys_set_inherit(Handle &, bool); unsigned sys_read(Handle &, char *, unsigned); unsigned sys_write(Handle &, const char *, unsigned); void sys_close(Handle &); diff --git a/source/io/memory.cpp b/source/io/memory.cpp index c5aee1e..eaaaeb1 100644 --- a/source/io/memory.cpp +++ b/source/io/memory.cpp @@ -42,6 +42,11 @@ void Memory::set_block(bool) throw logic_error("Memory::set_block"); } +void Memory::set_inherit(bool) +{ + throw logic_error("Memory::set_inherit"); +} + unsigned Memory::do_write(const char *buf, unsigned size) { check_access(M_WRITE); diff --git a/source/io/memory.h b/source/io/memory.h index 4df2aa3..4a6eca2 100644 --- a/source/io/memory.h +++ b/source/io/memory.h @@ -23,6 +23,7 @@ private: public: virtual void set_block(bool); + virtual void set_inherit(bool); private: virtual unsigned do_write(const char *, unsigned); diff --git a/source/io/mode.h b/source/io/mode.h index 2e7527d..0f7bb4f 100644 --- a/source/io/mode.h +++ b/source/io/mode.h @@ -13,7 +13,8 @@ enum Mode M_WRITE = 2, M_RDWR = M_READ|M_WRITE, M_APPEND = 4, - M_NONBLOCK = 8 + M_NONBLOCK = 8, + M_INHERIT = 16 }; inline Mode operator|(Mode m, Mode n) diff --git a/source/io/pipe.cpp b/source/io/pipe.cpp index 444f8c7..1301b3a 100644 --- a/source/io/pipe.cpp +++ b/source/io/pipe.cpp @@ -47,6 +47,13 @@ void Pipe::set_block(bool b) sys_set_blocking(write_handle, b); } +void Pipe::set_inherit(bool i) +{ + adjust_mode(mode, M_INHERIT, i); + sys_set_inherit(read_handle, i); + sys_set_inherit(write_handle, i); +} + unsigned Pipe::do_write(const char *buf, unsigned size) { if(size==0) diff --git a/source/io/pipe.h b/source/io/pipe.h index 2b2b76e..098e119 100644 --- a/source/io/pipe.h +++ b/source/io/pipe.h @@ -24,6 +24,7 @@ public: void set_mode(Mode); virtual void set_block(bool); + virtual void set_inherit(bool); protected: virtual unsigned do_write(const char *, unsigned); diff --git a/source/io/serial.cpp b/source/io/serial.cpp index b4cfaab..09a9768 100644 --- a/source/io/serial.cpp +++ b/source/io/serial.cpp @@ -46,6 +46,12 @@ void Serial::set_block(bool b) sys_set_blocking(handle, b); } +void Serial::set_inherit(bool i) +{ + adjust_mode(mode, M_INHERIT, i); + sys_set_inherit(handle, i); +} + void Serial::set_baud_rate(unsigned rate) { DeviceState state; diff --git a/source/io/serial.h b/source/io/serial.h index b219482..dbc7a77 100644 --- a/source/io/serial.h +++ b/source/io/serial.h @@ -36,6 +36,7 @@ private: public: virtual void set_block(bool); + virtual void set_inherit(bool); void set_baud_rate(unsigned); void set_data_bits(unsigned); diff --git a/source/io/slice.cpp b/source/io/slice.cpp index d53a63b..3fbfc57 100644 --- a/source/io/slice.cpp +++ b/source/io/slice.cpp @@ -26,6 +26,11 @@ void Slice::set_block(bool) throw logic_error("Slice::set_block"); } +void Slice::set_inherit(bool) +{ + throw logic_error("Slice::set_inherit"); +} + void Slice::flush() { sync_position = true; diff --git a/source/io/slice.h b/source/io/slice.h index fb45014..d5f0f74 100644 --- a/source/io/slice.h +++ b/source/io/slice.h @@ -29,6 +29,7 @@ public: Slice(Seekable &, SeekOffset, SeekOffset); virtual void set_block(bool); + virtual void set_inherit(bool); private: void flush(); diff --git a/source/io/unix/file.cpp b/source/io/unix/file.cpp index b2c9089..6092cb7 100644 --- a/source/io/unix/file.cpp +++ b/source/io/unix/file.cpp @@ -35,6 +35,8 @@ void File::platform_init(const string &fn, CreateMode cm) flags |= O_APPEND; if(mode&M_NONBLOCK) flags |= O_NONBLOCK; + if(!(mode&M_INHERIT)) + flags |= O_CLOEXEC; *handle = ::open(fn.c_str(), flags, 0666); if(!handle) diff --git a/source/io/unix/handle.cpp b/source/io/unix/handle.cpp index cb3ce4c..cbffa48 100644 --- a/source/io/unix/handle.cpp +++ b/source/io/unix/handle.cpp @@ -14,6 +14,12 @@ void sys_set_blocking(Handle &handle, bool b) fcntl(*handle, F_SETFL, (flags&~O_NONBLOCK)|(b?0:O_NONBLOCK)); } +void sys_set_inherit(Handle &handle, bool i) +{ + int flags = fcntl(*handle, F_GETFD); + fcntl(*handle, F_SETFD, (flags&~O_CLOEXEC)|(i?O_CLOEXEC:0)); +} + unsigned sys_read(Handle &handle, char *buf, unsigned size) { int ret = read(*handle, buf, size); diff --git a/source/io/windows/file.cpp b/source/io/windows/file.cpp index b973375..f6943ad 100644 --- a/source/io/windows/file.cpp +++ b/source/io/windows/file.cpp @@ -33,6 +33,11 @@ void File::platform_init(const string &fn, CreateMode cm) else share_flags = FILE_SHARE_READ; + SECURITY_ATTRIBUTES sec_attr; + sec_attr.nLength = sizeof(SECURITY_ATTRIBUTES); + sec_attr.lpSecurityDescriptor = 0; + sec_attr.bInheritHandle = !!(mode&M_INHERIT); + *handle = CreateFile(fn.c_str(), flags, share_flags, 0, create_flags, FILE_ATTRIBUTE_NORMAL, 0); if(!handle) { diff --git a/source/io/windows/handle.cpp b/source/io/windows/handle.cpp index 2dac33f..e59de27 100644 --- a/source/io/windows/handle.cpp +++ b/source/io/windows/handle.cpp @@ -9,6 +9,10 @@ void sys_set_blocking(Handle &, bool) { } +void sys_set_inherit(Handle &, bool) +{ +} + unsigned sys_read(Handle &handle, char *buf, unsigned size) { DWORD ret; diff --git a/source/io/zlibcompressed.cpp b/source/io/zlibcompressed.cpp index 99ae7f8..3ad4f22 100644 --- a/source/io/zlibcompressed.cpp +++ b/source/io/zlibcompressed.cpp @@ -118,6 +118,11 @@ void ZlibCompressed::set_block(bool) throw logic_error("ZlibCompressed::set_block"); } +void ZlibCompressed::set_inherit(bool) +{ + throw logic_error("ZlibCompressed::set_inherit"); +} + void ZlibCompressed::flush() { #ifdef WITH_ZLIB diff --git a/source/io/zlibcompressed.h b/source/io/zlibcompressed.h index fc559fe..af75aec 100644 --- a/source/io/zlibcompressed.h +++ b/source/io/zlibcompressed.h @@ -57,6 +57,7 @@ public: virtual ~ZlibCompressed(); virtual void set_block(bool); + virtual void set_inherit(bool); void flush();