名为信号的窗口未锁定

Windows Named Semaphore Not Getting Locked

本文关键字:锁定 窗口 信号      更新时间:2023-10-16

我正在开发带有Windows API C库的C 类。

我正在使用信号量进行任务,假设我有两个过程:

Processa有两个信号量:

全局 processa_receiving_semaphore

全局 processa_waiting_semaphore

ProcessB有两个信号量:

全局 processb_receiving_semaphore

全局 processb_waiting_semaphore

我在每个过程中都有两个线程:

在Processa中发送线程:

等待"全局 processb_waiting_semaphore"

//做某事

信号" global processb_receiving_semaphore"

在ProcessB上接收线程:

等待"全局 processb_receiving_semaphore"

//做某事

信号" global processb_waiting_semaphore

我删除了发布"全局 processb_waiting_semaphore"的所有代码。但仍然可以获取。在该信号量上调用WaitForSingleObject始终返回成功的等待和立即。我尝试将超时时间设置为0,但它仍然可以获取信号量,而没有任何释放。

接收信号量具有initial count = 0max count = 1,而等待信号量具有initial count = 1max count = 1

在接收信号量上调用WaitForSingleObject的功能很好,并且块块由另一个过程释放。问题在于等待信号量,我不知道原因。代码很大,我确保了信号量的名称已正确设置。

这是一个常见问题吗?如果您需要更多说明,请评论,我将修改帖子。


编辑:添加代码:

接收器信号量:

bool intr_process_comm::create_rcvr_semaphores()
{
  std::cout << "n  Creating semaphore: " << "Global\" << this_name << "_rcvr_sem";
  rcvr_sem = CreateSemaphore(NULL, 0, 1, ("Global\" + this_name + "_rcvr_sem").c_str());
  std::cout << "n  Creating semaphore: " << "Global\" << this_name << "_wait_sem";
  wait_sem = CreateSemaphore(NULL, 1, 1, ("Global\" + this_name + "_wait_sem").c_str());
  return (rcvr_sem && wait_sem);
}

发件人信号量:

// this sender connects to the wait semaphore in the target process
sndr_sem = OpenSemaphore(SEMAPHORE_MODIFY_STATE, FALSE, ("Global\" + target_name + "_wait_sem").c_str());
// this target connects to the receiver semaphore in the target process
trgt_sem = OpenSemaphore(SEMAPHORE_MODIFY_STATE, FALSE, ("Global\" + target_name + "_rcvr_sem").c_str());
DWORD intr_process_locking::wait(unsigned long period)
{
   return WaitForSingleObject(sndr_sem, period);
}
void intr_process_locking::signal()
{
   ReleaseSemaphore(trgt_sem, 1, 0);
}

接收线程功能:

void intr_process_comm::rcvr_thread_proc()
{
  while (conn_state == intr_process_comm::opened) {
    try {
      // wait on rcvr_semaphore for an infinite time
      WaitForSingleObject(rcvr_sem, INFINITE);
      if (inner_release) // if the semaphore was released within this process
        return;
      // once signaled by another process, get the message
      std::string msg_str((LPCSTR)hmf_mapview);
      // signal one of the waiters that want to put messages 
      // in this process's memory area
      // 
      // this doesn't change ANYTHING in execution, commented or not..
      //ReleaseSemaphore(wait_sem, 1, 0);
      // put this message in this process's queue
      Msg msg = Msg::from_xml(msg_str);
      if (msg.command == "connection")
        process_connection_message(msg);
  
      in_messages.enQ(msg);
      //std::cout << "n  Message: n"<< msg << "n";
    }
    catch (std::exception e) {
      std::cout << "n  Ran into trouble getting the message. Details: " << e.what();
    }
  }
}

发送线程功能:

void intr_process_comm::sndr_thread_proc()
{
  while (conn_state == intr_process_comm::opened ||
    (conn_state == intr_process_comm::closing && out_messages.size() > 0)
    ) {
    // pull a message out of the queue
    Msg msg = out_messages.deQ();
    if (connections.find(msg.destination) == connections.end())
      connections[msg.destination].connect(msg.destination);
    if (connections[msg.destination].connect(msg.destination)
      != intr_process_locking::state::opened) {
      blocked_messages[msg.destination].push_back(msg);
      continue;
    }
    // THIS ALWAYS GETS GETS WAIT_OBJECT_0 RESULT
    DWORD wait_result = connections[msg.destination].wait(wait_timeout);
    if (wait_result == WAIT_TIMEOUT) {  // <---- THIS IS NEVER TRUE
      out_messages.enQ(msg);
      continue;
    }
    // do things here
    // release the receiver semaphore in the other process
    connections[msg.destination].signal();
  }
}

澄清一些事情:

发件人中的

trgt_sem是接收器中的 rcvr_sem

发件人中的

`sndr_sem'是'wait_sem;在接收器中。

用于调用 WaitForSingleObject带有一些句柄:

手柄必须具有 SYNCHRONIZE 访问权利。

但是,您只需 SEMAPHORE_MODIFY_STATE 访问。使用此访问,可以调用ReleaseSemaphore(此句柄必须具有 SEMAPHORE_MODIFY_STATE 访问权利),但请致电WaitForSingleObject失败,结果WAIT_FAILED。在此之后,请致电GetLastError(),必须返回ERROR_ACCESS_DENIED

因此,如果我们要呼叫ReleaseSemaphore和任何等待功能 - 我们需要在手柄上具有 SEMAPHORE_MODIFY_STATE | SYNCHRONIZE 访问。因此需要使用代码

打开

OpenSemaphore(SEMAPHORE_MODIFY_STATE|SYNCHRONIZE, )

当然,总是检查API返回值和错误代码可以节省很多时间

如果将超时设置为0 waitforsingleobject将始终立即返回,那么成功的waitforsingleobject将返回wait_object_0(恰好具有值为0),wfso并不像大多数API一样,大多数API都指示了所指示的大多数API通过非零返回。