tty: some improvements to pass posix_openpt_test.
WriterLocker::AcquireWriter(): don't fail when the other end isn't yet opened. WriterLocker::_CheckBackgroundWrite(): don't fail when the pgrp_id differs. ReaderLocker::AcquireReader(): fail when the other end isn't opened anymore. ReaderLocker::AcquireReader(): check available bytes even in case of failure. ReaderLocker::_CheckBackgroundRead(): don't fail when the pgrp_id differs. Change-Id: Ice2bd119cbec2afc9ebd40714e4307856f540ea2 Reviewed-on: https://review.haiku-os.org/c/1418 Reviewed-by: Jérôme Duval <[email protected]>
This commit is contained in:
@@ -84,6 +84,8 @@ master_open(const char *name, uint32 flags, void **_cookie)
|
|||||||
return B_BUSY;
|
return B_BUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gMasterTTYs[index].opened_count = 0;
|
||||||
|
gSlaveTTYs[index].opened_count = 0;
|
||||||
status_t status = tty_open(&gMasterTTYs[index], &master_service);
|
status_t status = tty_open(&gMasterTTYs[index], &master_service);
|
||||||
if (status < B_OK) {
|
if (status < B_OK) {
|
||||||
// initializing TTY failed
|
// initializing TTY failed
|
||||||
|
|||||||
@@ -617,12 +617,8 @@ WriterLocker::AcquireWriter(bool dontBlock, size_t bytesNeeded)
|
|||||||
if (status == B_OK)
|
if (status == B_OK)
|
||||||
status = _CheckBackgroundWrite();
|
status = _CheckBackgroundWrite();
|
||||||
|
|
||||||
if (status == B_OK) {
|
if (status == B_OK)
|
||||||
if (fTarget->open_count > 0)
|
fBytes = _CheckAvailableBytes();
|
||||||
fBytes = _CheckAvailableBytes();
|
|
||||||
else
|
|
||||||
status = B_FILE_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
@@ -642,7 +638,6 @@ WriterLocker::_CheckBackgroundWrite() const
|
|||||||
&& processGroup != fSource->settings->pgrp_id) {
|
&& processGroup != fSource->settings->pgrp_id) {
|
||||||
if (team_get_controlling_tty() == fSource->index)
|
if (team_get_controlling_tty() == fSource->index)
|
||||||
send_signal(-processGroup, SIGTTOU);
|
send_signal(-processGroup, SIGTTOU);
|
||||||
return EIO;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
@@ -701,6 +696,13 @@ ReaderLocker::AcquireReader(bigtime_t timeout, size_t bytesNeeded)
|
|||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fCookie->other_tty->open_count == 0
|
||||||
|
&& fCookie->other_tty->opened_count > 0) {
|
||||||
|
TRACE(("ReaderLocker::AcquireReader() opened_count %" B_PRId32 "\n",
|
||||||
|
fCookie->other_tty->opened_count));
|
||||||
|
return B_FILE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
// We are not the first in queue or currently there's nothing to read:
|
// We are not the first in queue or currently there's nothing to read:
|
||||||
// bail out, if we shall not block.
|
// bail out, if we shall not block.
|
||||||
if (timeout <= 0)
|
if (timeout <= 0)
|
||||||
@@ -717,8 +719,10 @@ ReaderLocker::AcquireReader(bigtime_t timeout, size_t bytesNeeded)
|
|||||||
if (status == B_OK)
|
if (status == B_OK)
|
||||||
status = _CheckBackgroundRead();
|
status = _CheckBackgroundRead();
|
||||||
|
|
||||||
if (status == B_OK)
|
fBytes = _CheckAvailableBytes();
|
||||||
fBytes = _CheckAvailableBytes();
|
|
||||||
|
TRACE(("ReaderLocker::AcquireReader() ended status 0x%" B_PRIx32 "\n",
|
||||||
|
status));
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
@@ -751,7 +755,6 @@ ReaderLocker::_CheckBackgroundRead() const
|
|||||||
&& processGroup != fTTY->settings->pgrp_id) {
|
&& processGroup != fTTY->settings->pgrp_id) {
|
||||||
if (team_get_controlling_tty() == fTTY->index)
|
if (team_get_controlling_tty() == fTTY->index)
|
||||||
send_signal(-processGroup, SIGTTIN);
|
send_signal(-processGroup, SIGTTIN);
|
||||||
return EIO;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
@@ -825,6 +828,7 @@ reset_tty(struct tty* tty, int32 index, mutex* lock, bool isMaster)
|
|||||||
{
|
{
|
||||||
tty->ref_count = 0;
|
tty->ref_count = 0;
|
||||||
tty->open_count = 0;
|
tty->open_count = 0;
|
||||||
|
tty->opened_count = 0;
|
||||||
tty->index = index;
|
tty->index = index;
|
||||||
tty->lock = lock;
|
tty->lock = lock;
|
||||||
tty->settings = &gTTYSettings[index];
|
tty->settings = &gTTYSettings[index];
|
||||||
@@ -998,6 +1002,7 @@ add_tty_cookie(tty_cookie* cookie)
|
|||||||
// add to the TTY's cookie list
|
// add to the TTY's cookie list
|
||||||
cookie->tty->cookies.Add(cookie);
|
cookie->tty->cookies.Add(cookie);
|
||||||
cookie->tty->open_count++;
|
cookie->tty->open_count++;
|
||||||
|
cookie->tty->opened_count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1872,10 +1877,12 @@ tty_input_read(tty_cookie* cookie, void* _buffer, size_t* _length)
|
|||||||
TRACE(("tty_input_read: AcquireReader(%" B_PRIdBIGTIME "us, %ld)\n",
|
TRACE(("tty_input_read: AcquireReader(%" B_PRIdBIGTIME "us, %ld)\n",
|
||||||
timeout, bytesNeeded));
|
timeout, bytesNeeded));
|
||||||
status = locker.AcquireReader(timeout, bytesNeeded);
|
status = locker.AcquireReader(timeout, bytesNeeded);
|
||||||
if (status != B_OK)
|
|
||||||
break;
|
|
||||||
|
|
||||||
size_t toRead = locker.AvailableBytes();
|
size_t toRead = locker.AvailableBytes();
|
||||||
|
if (status != B_OK && toRead == 0) {
|
||||||
|
TRACE(("tty_input_read() AcquireReader failed\n"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (toRead > length)
|
if (toRead > length)
|
||||||
toRead = length;
|
toRead = length;
|
||||||
|
|
||||||
@@ -1914,6 +1921,8 @@ tty_input_read(tty_cookie* cookie, void* _buffer, size_t* _length)
|
|||||||
status = B_OK;
|
status = B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TRACE(("tty_input_read() status 0x%" B_PRIx32 "\n", status));
|
||||||
|
|
||||||
return *_length == 0 ? status : B_OK;
|
return *_length == 0 ? status : B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -131,6 +131,7 @@ struct tty_settings {
|
|||||||
struct tty {
|
struct tty {
|
||||||
int32 ref_count; // referenced by cookies
|
int32 ref_count; // referenced by cookies
|
||||||
int32 open_count;
|
int32 open_count;
|
||||||
|
int32 opened_count;
|
||||||
int32 index;
|
int32 index;
|
||||||
struct mutex* lock;
|
struct mutex* lock;
|
||||||
tty_settings* settings;
|
tty_settings* settings;
|
||||||
|
|||||||
@@ -170,7 +170,7 @@ public:
|
|||||||
|
|
||||||
if (semaphore >= 0) {
|
if (semaphore >= 0) {
|
||||||
TRACE(("TTYReference: cookie %p closed, last operation done, "
|
TRACE(("TTYReference: cookie %p closed, last operation done, "
|
||||||
"releasing blocking sem %ld\n", cookie, semaphore));
|
"releasing blocking sem %" B_PRId32 "\n", cookie, semaphore));
|
||||||
|
|
||||||
release_sem(semaphore);
|
release_sem(semaphore);
|
||||||
}
|
}
|
||||||
@@ -419,8 +419,8 @@ RequestOwner::Wait(bool interruptable, bigtime_t timeout)
|
|||||||
(interruptable ? B_CAN_INTERRUPT : 0) | B_RELATIVE_TIMEOUT,
|
(interruptable ? B_CAN_INTERRUPT : 0) | B_RELATIVE_TIMEOUT,
|
||||||
timeout);
|
timeout);
|
||||||
|
|
||||||
TRACE(("%p->RequestOwner::Wait(): condition occurred: %lx\n", this,
|
TRACE(("%p->RequestOwner::Wait(): condition occurred: %" B_PRIx32 "\n",
|
||||||
error));
|
this, error));
|
||||||
|
|
||||||
// remove the condition variable
|
// remove the condition variable
|
||||||
locker.Lock();
|
locker.Lock();
|
||||||
@@ -474,7 +474,8 @@ RequestOwner::Notify(Request* request)
|
|||||||
void
|
void
|
||||||
RequestOwner::NotifyError(Request* request, status_t error)
|
RequestOwner::NotifyError(Request* request, status_t error)
|
||||||
{
|
{
|
||||||
TRACE(("%p->RequestOwner::NotifyError(%p, %lx)\n", this, request, error));
|
TRACE(("%p->RequestOwner::NotifyError(%p, %" B_PRIx32 ")\n", this, request,
|
||||||
|
error));
|
||||||
|
|
||||||
if (fError == B_OK) {
|
if (fError == B_OK) {
|
||||||
fError = error;
|
fError = error;
|
||||||
@@ -602,12 +603,8 @@ WriterLocker::AcquireWriter(bool dontBlock, size_t bytesNeeded)
|
|||||||
status = fRequestOwner.Error();
|
status = fRequestOwner.Error();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status == B_OK) {
|
if (status == B_OK)
|
||||||
if (fTarget->open_count > 0)
|
fBytes = _CheckAvailableBytes();
|
||||||
fBytes = _CheckAvailableBytes();
|
|
||||||
else
|
|
||||||
status = B_FILE_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
@@ -661,6 +658,13 @@ ReaderLocker::AcquireReader(bigtime_t timeout, size_t bytesNeeded)
|
|||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fCookie->other_tty->open_count == 0
|
||||||
|
&& fCookie->other_tty->opened_count > 0) {
|
||||||
|
TRACE(("ReaderLocker::AcquireReader() opened_count %" B_PRId32 "\n",
|
||||||
|
fCookie->other_tty->opened_count));
|
||||||
|
return B_FILE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
// We are not the first in queue or currently there's nothing to read:
|
// We are not the first in queue or currently there's nothing to read:
|
||||||
// bail out, if we shall not block.
|
// bail out, if we shall not block.
|
||||||
if (timeout <= 0)
|
if (timeout <= 0)
|
||||||
@@ -674,8 +678,10 @@ ReaderLocker::AcquireReader(bigtime_t timeout, size_t bytesNeeded)
|
|||||||
status_t status = fRequestOwner.Wait(true, timeout);
|
status_t status = fRequestOwner.Wait(true, timeout);
|
||||||
Lock();
|
Lock();
|
||||||
|
|
||||||
if (status == B_OK)
|
fBytes = _CheckAvailableBytes();
|
||||||
fBytes = _CheckAvailableBytes();
|
|
||||||
|
TRACE(("ReaderLocker::AcquireReader() ended status 0x%" B_PRIx32 "\n",
|
||||||
|
status));
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
@@ -1328,6 +1334,7 @@ tty_create(tty_service_func func, bool isMaster)
|
|||||||
|
|
||||||
tty->ref_count = 0;
|
tty->ref_count = 0;
|
||||||
tty->open_count = 0;
|
tty->open_count = 0;
|
||||||
|
tty->opened_count = 0;
|
||||||
tty->select_pool = NULL;
|
tty->select_pool = NULL;
|
||||||
tty->is_master = isMaster;
|
tty->is_master = isMaster;
|
||||||
tty->pending_eof = 0;
|
tty->pending_eof = 0;
|
||||||
@@ -1391,6 +1398,7 @@ tty_create_cookie(struct tty* tty, struct tty* otherTTY, uint32 openMode)
|
|||||||
tty->cookies.Add(cookie);
|
tty->cookies.Add(cookie);
|
||||||
tty->open_count++;
|
tty->open_count++;
|
||||||
tty->ref_count++;
|
tty->ref_count++;
|
||||||
|
tty->opened_count++;
|
||||||
|
|
||||||
return cookie;
|
return cookie;
|
||||||
}
|
}
|
||||||
@@ -1568,10 +1576,12 @@ tty_read(tty_cookie* cookie, void* _buffer, size_t* _length)
|
|||||||
TRACE(("tty_input_read: AcquireReader(%Ldus, %ld)\n", timeout,
|
TRACE(("tty_input_read: AcquireReader(%Ldus, %ld)\n", timeout,
|
||||||
bytesNeeded));
|
bytesNeeded));
|
||||||
status = locker.AcquireReader(timeout, bytesNeeded);
|
status = locker.AcquireReader(timeout, bytesNeeded);
|
||||||
if (status != B_OK)
|
|
||||||
break;
|
|
||||||
|
|
||||||
size_t toRead = locker.AvailableBytes();
|
size_t toRead = locker.AvailableBytes();
|
||||||
|
if (status != B_OK && toRead == 0) {
|
||||||
|
TRACE(("tty_input_read() AcquireReader failed\n"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (toRead > length)
|
if (toRead > length)
|
||||||
toRead = length;
|
toRead = length;
|
||||||
|
|
||||||
@@ -1610,6 +1620,8 @@ tty_read(tty_cookie* cookie, void* _buffer, size_t* _length)
|
|||||||
status = B_OK;
|
status = B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TRACE(("tty_input_read() status 0x%" B_PRIx32 "\n", status));
|
||||||
|
|
||||||
return *_length == 0 ? status : B_OK;
|
return *_length == 0 ? status : B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -128,6 +128,7 @@ struct tty_settings {
|
|||||||
struct tty {
|
struct tty {
|
||||||
int32 ref_count; // referenced by cookies
|
int32 ref_count; // referenced by cookies
|
||||||
int32 open_count;
|
int32 open_count;
|
||||||
|
int32 opened_count;
|
||||||
struct mutex lock;
|
struct mutex lock;
|
||||||
tty_settings settings;
|
tty_settings settings;
|
||||||
select_sync_pool* select_pool;
|
select_sync_pool* select_pool;
|
||||||
|
|||||||
Reference in New Issue
Block a user