retVal = ASOCKERR_POLL;
return retVal;
}
+ asock->sendCbTimer = TRUE;
#else
/*
* For non-Windows platforms, just schedule a regular device callback.
* we check the latter if it wasn't the former.
*/
- removed = AsyncSocketPollRemove(asock, TRUE, POLL_FLAG_WRITE,
- asock->vt->sendCallback)
- || AsyncSocketPollRemove(asock, FALSE, 0, asock->vt->sendCallback);
+ if (asock->sendCbTimer) {
+ removed = AsyncSocketPollRemove(asock, FALSE, 0,
+ asock->vt->sendCallback);
+ } else {
+ removed = AsyncSocketPollRemove(asock, TRUE, POLL_FLAG_WRITE,
+ asock->vt->sendCallback);
+ }
ASSERT(removed || asock->pollParams.iPoll);
asock->sendCb = FALSE;
+ asock->sendCbTimer = FALSE;
}
}
NOT_IMPLEMENTED();
#else
AsyncSocket *asock = (AsyncSocket *) clientData;
- int error;
+ MXUserRecLock *lock;
ASSERT(asock);
ASSERT(asock->asockType != ASYNCSOCKET_TYPE_NAMEDPIPE);
!MXUser_IsCurThreadHoldingRecLock(asock->pollParams.lock));
AsyncSocketLock(asock);
- if (!asock->recvCb) {
- MXUserRecLock *lock = asock->pollParams.lock;
+ lock = asock->pollParams.lock;
+ if (asock->recvCb) {
+ /*
+ * There is no need to take a reference here -- the fact that this
+ * callback is running means AsyncsocketIPollRemove would not release a
+ * reference if it is called.
+ */
+ int error = AsyncSocketFillRecvBuffer(asock);
+
+ if (error == ASOCKERR_GENERIC || error == ASOCKERR_REMOTE_DISCONNECT) {
+ AsyncSocketHandleError(asock, error);
+ }
+ }
- /* Release the reference added when registering this callback. */
+ if (asock->recvCb) {
+ AsyncSocketUnlock(asock);
+ } else {
+ /*
+ * Callback has been unregistered. Per above, we need to release the
+ * reference explicitly.
+ */
AsyncSocketRelease(asock, TRUE);
if (lock != NULL) {
MXUser_DecRefRecLock(lock);
}
- return;
- }
-
- AsyncSocketAddRef(asock);
-
- error = AsyncSocketFillRecvBuffer(asock);
- if (error == ASOCKERR_GENERIC || error == ASOCKERR_REMOTE_DISCONNECT) {
- AsyncSocketHandleError(asock, error);
}
-
- AsyncSocketRelease(asock, TRUE);
#endif
}
AsyncSocketAddRef(s);
s->sendCb = FALSE; /* AsyncSocketSendCallback is never periodic */
+ s->sendCbTimer = FALSE;
retval = AsyncSocketWriteBuffers(s);
if (retval != ASOCKERR_SUCCESS) {
AsyncSocketHandleError(s, retval);
pollStatus = AsyncSocketPollAdd(s, FALSE, 0,
s->vt->sendCallback, 100000);
ASSERT_NOT_IMPLEMENTED(pollStatus == VMWARE_STATUS_SUCCESS);
+ s->sendCbTimer = TRUE;
} else
#endif
{
NOT_IMPLEMENTED();
#else
AsyncSocket *s = (AsyncSocket *) clientData;
- Bool removed;
+ MXUserRecLock *lock;
ASSERT(s);
ASSERT(s->asockType != ASYNCSOCKET_TYPE_NAMEDPIPE);
AsyncSocketLock(s);
- if (!s->sendCb) {
- MXUserRecLock *lock = s->pollParams.lock;
-
- /* Release the reference added when registering this callback. */
- AsyncSocketRelease(s, TRUE);
- if (lock != NULL) {
- MXUser_DecRefRecLock(lock);
+ lock = s->pollParams.lock;
+ if (s->sendCb) {
+ /*
+ * Unregister this callback as we want the non-periodic behavior. There
+ * is no need to take a reference here -- the fact that this callback is
+ * running means AsyncsocketIPollRemove would not release a reference.
+ * We would release that reference at the end.
+ */
+ if (s->sendCbTimer) {
+ AsyncSocketIPollRemove(s, FALSE, 0, AsyncSocketIPollSendCallback);
+ } else {
+ AsyncSocketIPollRemove(s, TRUE, POLL_FLAG_WRITE,
+ AsyncSocketIPollSendCallback);
}
- return;
- }
- AsyncSocketAddRef(s);
-
- /* Unregister this callback as we want the non-periodic behavior. */
- removed = AsyncSocketIPollRemove(s, TRUE, POLL_FLAG_WRITE,
- AsyncSocketIPollSendCallback) ||
- AsyncSocketIPollRemove(s, FALSE, 0, AsyncSocketIPollSendCallback);
-
- AsyncSocketSendCallback(s);
+ AsyncSocketSendCallback(s);
+ }
AsyncSocketRelease(s, TRUE);
+ if (lock != NULL) {
+ MXUser_DecRefRecLock(lock);
+ }
#endif
}