Implement controls for file descriptor inheritance
authorMikko Rasa <tdb@tdb.fi>
Sat, 2 Dec 2017 15:03:10 +0000 (17:03 +0200)
committerMikko Rasa <tdb@tdb.fi>
Sat, 2 Dec 2017 15:03:10 +0000 (17:03 +0200)
24 files changed:
source/core/unix/process.cpp
source/io/base.h
source/io/buffered.cpp
source/io/buffered.h
source/io/console.cpp
source/io/console.h
source/io/file.cpp
source/io/file.h
source/io/handle.h
source/io/memory.cpp
source/io/memory.h
source/io/mode.h
source/io/pipe.cpp
source/io/pipe.h
source/io/serial.cpp
source/io/serial.h
source/io/slice.cpp
source/io/slice.h
source/io/unix/file.cpp
source/io/unix/handle.cpp
source/io/windows/file.cpp
source/io/windows/handle.cpp
source/io/zlibcompressed.cpp
source/io/zlibcompressed.h

index 76141b0360a56de7ed150878430f4a6848a26279..99be2e1d75a592a87a07e926439add7a4a5bec17 100644 (file)
@@ -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)
index 1fe143e10e18eed4668aac843c3d4905b54f3ede..a6a8827c6d4c28ee981806c4284af063b96de8dd 100644 (file)
@@ -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; }
 
index 6567fff9b3739e4fabf8abb1f2a706a98e0d5d85..2836e4bbbaeb879de07be26bf5fba2ecea8fcad9 100644 (file)
@@ -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)
index c88f0f8ece1836d8c0da7d8840d92d8a284f9be4..da917e0c5a6585027a469ad4fa5dc814db517c29 100644 (file)
@@ -22,6 +22,7 @@ public:
        ~Buffered();
 
        virtual void set_block(bool);
+       virtual void set_inherit(bool);
 
        void flush();
 
index e70f31d6a4aa21e8d8498559200423fc3a667f5c..a7417edcee8f186263c965363f4942d9b1f82768 100644 (file)
@@ -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);
index e2b5d533cc0f1ac6d45749fbbbde7f9b712b5688..8feccfd2ffe74a2fd3e1e05d69310e887eb7c0d6 100644 (file)
@@ -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.  */
index ab957c97f1e2472a5d007b86e8ace3ea9493ec59..74b9f9fde19e49983e35098ea06c0c6c80bcfd0e 100644 (file)
@@ -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);
index ececa8dc19c28f53d2e690db06af481a81555e52..85075d0cca6e8709db663012ced369dd5f0cda52 100644 (file)
@@ -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);
index 8a9db50b60ec5e85032fa5e1eb0741f9857cbdfe..4b311f545f3212ff8755b7dbbf51c2889991d1b5 100644 (file)
@@ -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 &);
index c5aee1e0536e040e72187172b2c084269596cce9..eaaaeb1829dfc5a59b481ca32e6e48170a78cc53 100644 (file)
@@ -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);
index 4df2aa3b6cb4d4d848c4435c14be8eeefa93a52c..4a6eca2ab44178636a0fa3016c97910f8834230f 100644 (file)
@@ -23,6 +23,7 @@ private:
 
 public:
        virtual void set_block(bool);
+       virtual void set_inherit(bool);
 
 private:
        virtual unsigned do_write(const char *, unsigned);
index 2e7527dc5202d3158895f8c20feb3f90236b17dd..0f7bb4fc37650cabe29389021d9c06be0b64bebe 100644 (file)
@@ -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)
index 444f8c72a3c3bcc986935f698c3d4b62e61b1a37..1301b3ad0a8ce2a8554157d3d737bfa99b9bd06a 100644 (file)
@@ -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)
index 2b2b76ef25ee47f2e75c597255a2a99e1e1a09e0..098e1190a63ecd1882e453c49fc727006b7c861e 100644 (file)
@@ -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);
index b4cfaab4726718bbfaa5f450cd3c1d7e1bcf29eb..09a9768023bad9e1fa00be0d398ac45a6933442c 100644 (file)
@@ -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;
index b2194821e2691278877d473f8e30b552b3a42de7..dbc7a77bd0578159d12a8ae3b0d202290a604162 100644 (file)
@@ -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);
index d53a63b13bd17a966f11de2f4766fb57e8880807..3fbfc5756f4e5ff4173eaf30e6ceedc1a2815591 100644 (file)
@@ -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;
index fb4501483bd56e0956ac9b6775d352b53d2ad508..d5f0f748102748696ab2bdaf05abf0985a7a70a7 100644 (file)
@@ -29,6 +29,7 @@ public:
        Slice(Seekable &, SeekOffset, SeekOffset);
 
        virtual void set_block(bool);
+       virtual void set_inherit(bool);
 
 private:
        void flush();
index b2c9089a8d6ecdf108aee88ec30ab38b7b6732bd..6092cb740172365d878be540121abf565582a949 100644 (file)
@@ -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)
index cb3ce4cae54c16aae8ceb83194044aac98aca94c..cbffa48e62a7354522a8d9efb8fcafe8f8c36c60 100644 (file)
@@ -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);
index b973375475abe3554296969bb5a19ed836fbbe2f..f6943adb3cb397cf3be67c8f76f4a9989cd9a2d2 100644 (file)
@@ -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)
        {
index 2dac33fa2b531dc88db375bea661f5b991aa6a15..e59de273a65ea07d3d42712f1d2394cdc0db018d 100644 (file)
@@ -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;
index 99ae7f81f8845016e73e92d60f13083e7e672ee6..3ad4f224a14f0ca9b9c2fb29d5e4df70a851c4b2 100644 (file)
@@ -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
index fc559febcbdb837036cd35b0f7d3aeb9d0248c37..af75aecd51d7d843d92390be68cb1a955e52e2a0 100644 (file)
@@ -57,6 +57,7 @@ public:
        virtual ~ZlibCompressed();
 
        virtual void set_block(bool);
+       virtual void set_inherit(bool);
 
        void flush();