- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我想收集已终止子进程的 pid,但与信号处理程序通信时遇到问题...我没有 c(++)11。这是有效的吗?另请考虑到我的程序将是多线程的(但队列将仅从一个线程使用)。
#include <iostream>
#include <csignal>
#include <cstdlib>
#include <cstdio>
#include <unistd.h>
#include <sys/wait.h>
template<typename _ValueType, int _Capacity>
class signal_result_queue
{
public:
static const int capacity = _Capacity;
typedef _ValueType value_type;
private:
//+1 so we can distinguish empty from full
volatile value_type _data[capacity+1];
volatile sig_atomic_t _base;
volatile sig_atomic_t _next;
volatile sig_atomic_t _overflows;
public:
signal_result_queue()
: _base(0)
, _next(0)
, _overflows(0)
{}
void push_sh(value_type value)
{
int base = _base; // we are not interrupted anyway
int next = _next; // same here
int before_base = wrap(base-1);
if(next == before_base)
{
++_overflows;
}
else
{
_data[next] = value;
_next = wrap(next+1);
}
}
int overflows_t1()
{
int overflows = _overflows;
_overflows -= overflows;
return overflows;
}
bool pop_t1(value_type& result)
{
// this is only changed by us.
int base = _base;
// It might increase but no problem
int next = _next;
if(base == next)
{
return false;
}
else
{
result = _data[base];
_base = wrap(base+1);
return true;
}
}
private:
static int wrap( int i )
{
while(i>=capacity+1)
{
i-=(capacity+1);
}
while(i<0)
{
i+=(capacity+1);
}
return i;
}
};
signal_result_queue<pid_t, 20> q;
void sigchld_handler(int)
{
pid_t pid;
while((pid = waitpid(static_cast<pid_t>(-1), 0, WNOHANG)) > 0){
q.push_sh(pid);
}
}
int main()
{
struct sigaction sa;
sa.sa_handler = &sigchld_handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART | SA_NOCLDSTOP;
if (sigaction(SIGCHLD, &sa, 0) == -1) {
perror(0);
std::exit(1);
}
for(int i=0;i<10;i++)
{
pid_t pid = fork();
if(pid == 0) // child
{
sleep(i);
return 0;
}
else if(pid == -1) // error
{
std::cout << "fork error" << std::endl;
}
else // parent
{
std::cout << "fork pid: " << pid << std::endl;
}
}
int terminated = 0;
do
{
sleep(1);
int overflows = q.overflows_t1();
if(overflows > 0)
{
std::cout << "Overflow in queue:" << overflows << std::endl;
}
pid_t val;
while(q.pop_t1(val))
{
terminated++;
std::cout << "Terminated: " << val << std::endl;
}
} while(terminated < 10);
return 0;
}
最佳答案
这不是一种安全的方法,原因有两个:
volatile
不足以避免多线程程序中的竞争情况。 sig_atomic_t 对于信号重入来说保证是原子的,但我怀疑它对于多线程来说是否足够。使用 C++11,您可以使用原子而不是 volatile 。如果没有 C++11,您需要使用 mutex lock 来保护对队列的并发访问。保护对共享变量的访问。这样就可以解决上述两个问题。
如有疑问,请进行额外演示:
只是为了更详细地说明它是多么不安全:
假设处理第一个进程信号:
int base = _base; // acces to _base is atomic. It's protected ONLY DURING THE STATEMENT
int next = _next; // same here
int before_base = wrap(base-1);
现在想象另一个线程调用处理程序,并在 CPU 上运行。为简单起见,假设第一个被系统调度程序搁置。因此处理程序的第二个实例执行:
int base = _base; // SAME BASE IS STORED LOCALLY
int next = _next; // SAME NEXT IS STORED LOCALLY
int before_base = wrap(base-1);
因此,此时,处理程序的两个实例在其本地拷贝 base
和 next
中具有相同的索引。现在第二个实例继续:
...
_data[next] = value; // value is stored in the queue
_next = wrap(next+1); // and _next is incremented.
这里调度程序再次唤醒第一个实例,该实例立即继续:
_data[next] = value; // USES ITS LOCAL COPY OF NEXT, WRITE IN SAME PLACE THAN THE OTHER INSTANCE !!
_next = wrap(next+1); // and _next is incremented BASED ON LOCAL COPY.
因此此时,在您的队列中,您将只有应该存储的两个值之一。
关于c++ - 这是从信号处理程序返回值的可靠方法吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29183389/
#include using namespace std; class C{ private: int value; public: C(){ value = 0;
这个问题已经有答案了: What is the difference between char a[] = ?string?; and char *p = ?string?;? (8 个回答) 已关闭
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 7 年前。 此帖子已于 8 个月
除了调试之外,是否有任何针对 c、c++ 或 c# 的测试工具,其工作原理类似于将独立函数复制粘贴到某个文本框,然后在其他文本框中输入参数? 最佳答案 也许您会考虑单元测试。我推荐你谷歌测试和谷歌模拟
我想在第二台显示器中移动一个窗口 (HWND)。问题是我尝试了很多方法,例如将分辨率加倍或输入负值,但它永远无法将窗口放在我的第二台显示器上。 关于如何在 C/C++/c# 中执行此操作的任何线索 最
我正在寻找 C/C++/C## 中不同类型 DES 的现有实现。我的运行平台是Windows XP/Vista/7。 我正在尝试编写一个 C# 程序,它将使用 DES 算法进行加密和解密。我需要一些实
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
有没有办法强制将另一个 窗口置于顶部? 不是应用程序的窗口,而是另一个已经在系统上运行的窗口。 (Windows, C/C++/C#) 最佳答案 SetWindowPos(that_window_ha
假设您可以在 C/C++ 或 Csharp 之间做出选择,并且您打算在 Windows 和 Linux 服务器上运行同一服务器的多个实例,那么构建套接字服务器应用程序的最明智选择是什么? 最佳答案 如
你们能告诉我它们之间的区别吗? 顺便问一下,有什么叫C++库或C库的吗? 最佳答案 C++ 标准库 和 C 标准库 是 C++ 和 C 标准定义的库,提供给 C++ 和 C 程序使用。那是那些词的共同
下面的测试代码,我将输出信息放在注释中。我使用的是 gcc 4.8.5 和 Centos 7.2。 #include #include class C { public:
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
我的客户将使用名为 annoucement 的结构/类与客户通信。我想我会用 C++ 编写服务器。会有很多不同的类继承annoucement。我的问题是通过网络将这些类发送给客户端 我想也许我应该使用
我在 C# 中有以下函数: public Matrix ConcatDescriptors(IList> descriptors) { int cols = descriptors[0].Co
我有一个项目要编写一个函数来对某些数据执行某些操作。我可以用 C/C++ 编写代码,但我不想与雇主共享该函数的代码。相反,我只想让他有权在他自己的代码中调用该函数。是否可以?我想到了这两种方法 - 在
我使用的是编写糟糕的第 3 方 (C/C++) Api。我从托管代码(C++/CLI)中使用它。有时会出现“访问冲突错误”。这使整个应用程序崩溃。我知道我无法处理这些错误[如果指针访问非法内存位置等,
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 7 年前。
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,因为
我有一些 C 代码,将使用 P/Invoke 从 C# 调用。我正在尝试为这个 C 函数定义一个 C# 等效项。 SomeData* DoSomething(); struct SomeData {
这个问题已经有答案了: Why are these constructs using pre and post-increment undefined behavior? (14 个回答) 已关闭 6
我是一名优秀的程序员,十分优秀!