/* Shim for on_dsm_callback. */ static void shm_mq_detach_callback(dsm_segment *seg, Datum arg) { shm_mq *mq = (shm_mq *) DatumGetPointer(arg); shm_mq_detach(mq); }
/* * Clean up at end of an executor run */ static void tqueueShutdownReceiver(DestReceiver *self) { TQueueDestReceiver *tqueue = (TQueueDestReceiver *) self; if (tqueue->queue != NULL) shm_mq_detach(tqueue->queue); tqueue->queue = NULL; }
/* * Destroy receiver when done with it */ static void tqueueDestroyReceiver(DestReceiver *self) { TQueueDestReceiver *tqueue = (TQueueDestReceiver *) self; /* We probably already detached from queue, but let's be sure */ if (tqueue->queue != NULL) shm_mq_detach(tqueue->queue); pfree(self); }
/* * Transmit a libpq protocol message to the shared memory message queue * selected via pq_mq_handle. We don't include a length word, because the * receiver will know the length of the message from shm_mq_receive(). */ static int mq_putmessage(char msgtype, const char *s, size_t len) { shm_mq_iovec iov[2]; shm_mq_result result; /* * If we're sending a message, and we have to wait because the queue is * full, and then we get interrupted, and that interrupt results in trying * to send another message, we respond by detaching the queue. There's no * way to return to the original context, but even if there were, just * queueing the message would amount to indefinitely postponing the * response to the interrupt. So we do this instead. */ if (pq_mq_busy) { if (pq_mq != NULL) shm_mq_detach(pq_mq); pq_mq = NULL; pq_mq_handle = NULL; return EOF; } /* * If the message queue is already gone, just ignore the message. This * doesn't necessarily indicate a problem; for example, DEBUG messages * can be generated late in the shutdown sequence, after all DSMs have * already been detached. */ if (pq_mq == NULL) return 0; pq_mq_busy = true; iov[0].data = &msgtype; iov[0].len = 1; iov[1].data = s; iov[1].len = len; Assert(pq_mq_handle != NULL); for (;;) { result = shm_mq_sendv(pq_mq_handle, iov, 2, true); if (pq_mq_parallel_master_pid != 0) SendProcSignal(pq_mq_parallel_master_pid, PROCSIG_PARALLEL_MESSAGE, pq_mq_parallel_master_backend_id); if (result != SHM_MQ_WOULD_BLOCK) break; WaitLatch(&MyProc->procLatch, WL_LATCH_SET, 0); CHECK_FOR_INTERRUPTS(); ResetLatch(&MyProc->procLatch); } pq_mq_busy = false; Assert(result == SHM_MQ_SUCCESS || result == SHM_MQ_DETACHED); if (result != SHM_MQ_SUCCESS) return EOF; return 0; }