summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Kling <awesomekling@gmail.com>2019-02-05 12:27:32 +0100
committerAndreas Kling <awesomekling@gmail.com>2019-02-05 12:27:32 +0100
commit378e20c535a3f8b7f6f5519a1a3fe6b1c4949a12 (patch)
treeccc97448aafbcf3fd4aeb03fd7d90bef70d9ca34
parent3accdb0e93eeb90898b3fd1b15e733163461d29b (diff)
downloadserenity-378e20c535a3f8b7f6f5519a1a3fe6b1c4949a12.zip
Kernel: Reading from a slave PTY should give EOF if master PTY is closed.
-rw-r--r--Kernel/MasterPTY.cpp9
-rw-r--r--Kernel/MasterPTY.h15
-rw-r--r--Kernel/SlavePTY.cpp14
-rw-r--r--Kernel/SlavePTY.h2
-rw-r--r--Userland/sh.cpp2
5 files changed, 35 insertions, 7 deletions
diff --git a/Kernel/MasterPTY.cpp b/Kernel/MasterPTY.cpp
index f1a88103d3..40511ac501 100644
--- a/Kernel/MasterPTY.cpp
+++ b/Kernel/MasterPTY.cpp
@@ -69,3 +69,12 @@ bool MasterPTY::can_write_from_slave() const
{
return m_buffer.bytes_in_write_buffer() < 4096;
}
+
+void MasterPTY::close()
+{
+ if (retain_count() == 2) {
+ // After the closing FileDescriptor dies, slave is the only thing keeping me alive.
+ // From this point, let's consider ourselves closed.
+ m_closed = true;
+ }
+}
diff --git a/Kernel/MasterPTY.h b/Kernel/MasterPTY.h
index 29d7106927..7f2ebbaf02 100644
--- a/Kernel/MasterPTY.h
+++ b/Kernel/MasterPTY.h
@@ -11,24 +11,25 @@ public:
explicit MasterPTY(unsigned index);
virtual ~MasterPTY() override;
- // ^CharacterDevice
- virtual ssize_t read(Process&, byte*, size_t) override;
- virtual ssize_t write(Process&, const byte*, size_t) override;
- virtual bool can_read(Process&) const override;
- virtual bool can_write(Process&) const override;
- virtual bool is_master_pty() const override { return true; }
-
unsigned index() const { return m_index; }
String pts_name() const;
void on_slave_write(const byte*, size_t);
bool can_write_from_slave() const;
void notify_slave_closed(Badge<SlavePTY>);
+ bool is_closed() const { return m_closed; }
private:
// ^CharacterDevice
+ virtual ssize_t read(Process&, byte*, size_t) override;
+ virtual ssize_t write(Process&, const byte*, size_t) override;
+ virtual bool can_read(Process&) const override;
+ virtual bool can_write(Process&) const override;
+ virtual void close() override;
+ virtual bool is_master_pty() const override { return true; }
virtual const char* class_name() const override { return "MasterPTY"; }
RetainPtr<SlavePTY> m_slave;
unsigned m_index;
+ bool m_closed { false };
DoubleBuffer m_buffer;
};
diff --git a/Kernel/SlavePTY.cpp b/Kernel/SlavePTY.cpp
index f5c0b1872a..651c4d82cf 100644
--- a/Kernel/SlavePTY.cpp
+++ b/Kernel/SlavePTY.cpp
@@ -43,6 +43,20 @@ bool SlavePTY::can_write(Process&) const
return m_master->can_write_from_slave();
}
+bool SlavePTY::can_read(Process& process) const
+{
+ if (m_master->is_closed())
+ return true;
+ return TTY::can_read(process);
+}
+
+ssize_t SlavePTY::read(Process& process, byte* buffer, size_t size)
+{
+ if (m_master->is_closed())
+ return 0;
+ return TTY::read(process, buffer, size);
+}
+
void SlavePTY::close()
{
m_master->notify_slave_closed(Badge<SlavePTY>());
diff --git a/Kernel/SlavePTY.h b/Kernel/SlavePTY.h
index 4768a707a5..9aae22e373 100644
--- a/Kernel/SlavePTY.h
+++ b/Kernel/SlavePTY.h
@@ -20,6 +20,8 @@ private:
virtual void on_tty_write(const byte*, size_t) override;
// ^CharacterDevice
+ virtual bool can_read(Process&) const override;
+ virtual ssize_t read(Process&, byte*, size_t) override;
virtual bool can_write(Process&) const override;
virtual const char* class_name() const override { return "SlavePTY"; }
virtual void close() override;
diff --git a/Userland/sh.cpp b/Userland/sh.cpp
index 0fc4ee4642..0e49297420 100644
--- a/Userland/sh.cpp
+++ b/Userland/sh.cpp
@@ -410,6 +410,8 @@ int main(int argc, char** argv)
for (;;) {
char keybuf[16];
ssize_t nread = read(0, keybuf, sizeof(keybuf));
+ if (nread == 0)
+ return 0;
if (nread < 0) {
if (errno == EINTR) {
ASSERT(g->was_interrupted);