/* * ipc_finish() - * * Locks and destroys the semaphore set and message queue if called * in the daemonized queue runner. If force isn't given, it will * only do so if the archive queue is empty after locking the set * and draining the message queue. */ int ipc_finish(bool force) { if (ipc_creator) { if (!force) { /* * We are the creator of the semaphore set, so if this isn't * a force operation, we lock it first, poll the message queue * and check that we have an empty queue. */ if (ipc_lock() < 0) { fprintf(stderr, "semop() failed in ipc_finish(): %s\n", strerror(errno)); return -1; } if (ipc_poll(false) < 0) return -1; if (archive_queue_head != NULL) { if (ipc_unlock() < 0) { fprintf(stderr, "semop() failed in ipc_finish(): %s\n", strerror(errno)); return -1; } return 1; } } /* * At this point, we are either forced to stop or we have a lock * and the queue is empty. */ if (msgctl(msgid, IPC_RMID, NULL) < 0) { fprintf(stderr, "msgctl() failed in ipc_finish(): %s\n", strerror(errno)); semctl(semid, 0, IPC_RMID); return -1; } if (semctl(semid, 0, IPC_RMID) < 0) { fprintf(stderr, "semctl() failed in ipc_finish(): %s\n", strerror(errno)); return -1; } } return 0; }
/* * ipc_send_code() - * * Support function for ipc_send_term() and ipc_send_resume(). */ static int ipc_send_code(char *archive_dir, int code) { struct { long mtype; char mtext[1]; } msg; if (ipc_generate_keys(archive_dir) < 0) return -1; if ((semid = semget(semkey, 0, 0)) < 0) { if (!opt_quiet) fprintf(stderr, "no logshipper daemon running\n"); return 2; } if (ipc_lock() < 0) return -1; if ((msgid = msgget(msgkey, 0)) < 0) { fprintf(stderr, "msgget() failed in ipc_send_code(): %s\n", strerror(errno)); ipc_unlock(); return -1; } msg.mtype = (long)code; if (msgsnd(msgid, &msg, 0, 0) < 0) { fprintf(stderr, "msgsnd() failed in ipc_send_code(): %s\n", strerror(errno)); ipc_unlock(); return -1; } return ipc_unlock(); }
/* * freeque() wakes up waiters on the sender and receiver waiting queue, * removes the message queue from message queue ID IDR, and cleans up all the * messages associated with this queue. * * msg_ids.rw_mutex (writer) and the spinlock for this message queue are held * before freeque() is called. msg_ids.rw_mutex remains locked on exit. */ static void freeque(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp) { struct list_head *tmp; struct msg_queue *msq = container_of(ipcp, struct msg_queue, q_perm); expunge_all(msq, -EIDRM); ss_wakeup(&msq->q_senders, 1); msg_rmid(ns, msq); msg_unlock(msq); tmp = msq->q_messages.next; while (tmp != &msq->q_messages) { struct msg_msg *msg = list_entry(tmp, struct msg_msg, m_list); tmp = tmp->next; atomic_dec(&ns->msg_hdrs); free_msg(msg); } atomic_sub(msq->q_cbytes, &ns->msg_bytes); security_msg_queue_free(msq); ipc_lock_by_ptr(&msq->q_perm); ipc_rcu_putref(msq); ipc_unlock(&msq->q_perm); }
static inline void sem_putref(struct sem_array *sma) { ipc_lock_by_ptr(&sma->sem_perm); ipc_rcu_putref(sma); ipc_unlock(&(sma)->sem_perm); }
static inline void sem_getref_and_unlock(struct sem_array *sma) { ipc_rcu_getref(sma); ipc_unlock(&(sma)->sem_perm); }