* Implemented a different way to notify waiting read()s when a file descriptor

is closed; their ReadRequest will now be notified with B_FILE_ERROR.
* This is a better fix for #5947, though note that I left the changes in
  Inode::ReadDataFromBuffer() in place, as I think this is what POSIX requires.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@37860 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2010-08-03 06:55:28 +00:00
parent b9857cc356
commit 81fcd71e3a
+26 -9
View File
@@ -51,8 +51,11 @@
namespace fifo {
struct file_cookie;
class Inode;
class RingBuffer {
public:
RingBuffer();
@@ -76,9 +79,10 @@ class RingBuffer {
class ReadRequest : public DoublyLinkedListLinkImpl<ReadRequest> {
public:
ReadRequest()
ReadRequest(file_cookie* cookie)
:
fThread(thread_get_current_thread()),
fCookie(cookie),
fNotified(true)
{
B_INITIALIZE_SPINLOCK(&fLock);
@@ -90,21 +94,27 @@ class ReadRequest : public DoublyLinkedListLinkImpl<ReadRequest> {
fNotified = notified;
}
void Notify()
void Notify(status_t status = B_OK)
{
InterruptsSpinLocker _(fLock);
TRACE("ReadRequest %p::Notify(), fNotified %d\n", this, fNotified);
if (!fNotified) {
SpinLocker threadLocker(gThreadSpinlock);
thread_unblock_locked(fThread, B_OK);
thread_unblock_locked(fThread, status);
fNotified = true;
}
}
file_cookie* Cookie() const
{
return fCookie;
}
private:
spinlock fLock;
struct thread* fThread;
file_cookie* fCookie;
volatile bool fNotified;
};
@@ -165,7 +175,7 @@ class Inode {
void NotifyEndClosed(bool writer);
void Open(int openMode);
void Close(int openMode);
void Close(int openMode, file_cookie* cookie);
int32 ReaderCount() const { return fReaderCount; }
int32 WriterCount() const { return fWriterCount; }
@@ -215,7 +225,7 @@ struct file_cookie {
};
//---------------------
// #pragma mark -
RingBuffer::RingBuffer()
@@ -390,7 +400,7 @@ Inode::WriteDataToBuffer(const void *_data, size_t *_length, bool nonBlocking)
}
// write only as long as there are readers left
if (fReaderCount == 0) {
if (fActive && fReaderCount == 0) {
if (written == 0)
send_signal(find_thread(NULL), SIGPIPE);
return EPIPE;
@@ -615,12 +625,19 @@ Inode::Open(int openMode)
void
Inode::Close(int openMode)
Inode::Close(int openMode, file_cookie* cookie)
{
TRACE("Inode %p::Close(openMode = %d)\n", this, openMode);
MutexLocker locker(RequestLock());
// Notify all currently reading file descriptors
ReadRequestList::Iterator iterator = fReadRequests.GetIterator();
while (ReadRequest* request = iterator.Next()) {
if (request->Cookie() == cookie)
request->Notify(B_FILE_ERROR);
}
if ((openMode & O_ACCMODE) == O_WRONLY && --fWriterCount == 0)
NotifyEndClosed(true);
@@ -750,7 +767,7 @@ fifo_close(fs_volume *volume, fs_vnode *vnode, void *_cookie)
file_cookie *cookie = (file_cookie *)_cookie;
FIFOInode* fifo = (FIFOInode*)vnode->private_node;
fifo->Close(cookie->open_mode);
fifo->Close(cookie->open_mode, cookie);
return B_OK;
}
@@ -802,7 +819,7 @@ fifo_read(fs_volume *_volume, fs_vnode *_node, void *_cookie,
// issue read request
ReadRequest request;
ReadRequest request(cookie);
inode->AddReadRequest(request);
TRACE(" issue read request %p\n", &request);