mmlr+bonefish(+axeld - I put the bug in there ;-)):
* Inode::MayReleaseWriter() would release the semaphore too often; therefore, Inode::WriteDataToBuffer() now loops in case it still couldn't write anything instead of failing - this fixes a race condition (ie. a device is full message). * In case the read request got filled two times (while adding the request, and after waiting for it to become filled), ReadRequest::PutBuffer() overwrote the output data. This fixes bug #1331. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21830 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -626,17 +626,19 @@ Inode::WriteDataToBuffer(const void **_data, size_t *_bytesLeft,
|
|||||||
// still come in and we don't block the whole inode data transfer
|
// still come in and we don't block the whole inode data transfer
|
||||||
// to prevent deadlocks from happening
|
// to prevent deadlocks from happening
|
||||||
|
|
||||||
if (!nonBlocking)
|
while (fBuffer.Writable() == 0) {
|
||||||
|
if (nonBlocking)
|
||||||
|
return B_WOULD_BLOCK;
|
||||||
|
|
||||||
benaphore_unlock(&fRequestLock);
|
benaphore_unlock(&fRequestLock);
|
||||||
|
|
||||||
status_t status = acquire_sem_etc(fWriteLock, 1,
|
status_t status = acquire_sem_etc(fWriteLock, 1, B_CAN_INTERRUPT, 0);
|
||||||
(nonBlocking ? B_TIMEOUT : 0) | B_CAN_INTERRUPT, 0);
|
|
||||||
|
|
||||||
if (!nonBlocking)
|
|
||||||
benaphore_lock(&fRequestLock);
|
benaphore_lock(&fRequestLock);
|
||||||
|
|
||||||
if (status != B_OK)
|
if (status != B_OK)
|
||||||
return status;
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
// ensure that we don't write more than PIPEFS_MAX_BUFFER_SIZE
|
// ensure that we don't write more than PIPEFS_MAX_BUFFER_SIZE
|
||||||
// into a pipe without blocking
|
// into a pipe without blocking
|
||||||
@@ -1007,7 +1009,7 @@ ReadRequest::PutBuffer(RingBuffer &buffer, size_t *_bytesRead,
|
|||||||
if (length == 0)
|
if (length == 0)
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
|
||||||
if (buffer.UserRead(fBuffer, length) < B_OK) {
|
if (buffer.UserRead((char*)fBuffer + fBytesRead, length) < B_OK) {
|
||||||
// if the buffer is just invalid, we release the reader as well
|
// if the buffer is just invalid, we release the reader as well
|
||||||
release_sem(fLock);
|
release_sem(fLock);
|
||||||
return B_BAD_ADDRESS;
|
return B_BAD_ADDRESS;
|
||||||
|
|||||||
Reference in New Issue
Block a user