- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
以下程序处理nbFiles
每个 GROUPSIZE
使用 1 个工作线程的文件文件。不超过MAXNBRTHREADS
工作线程是并行运行的。一个watchDog()
线程(线程 0)用于管理 PTHREAD_CANCEL_DEFERRED
相同的 worker 。如果任何一个 worker 失败了,它 pthread_cond_signal(&errCv)
watchDog
在全局互斥体的保护下mtx
,通过 errIndc
传递其线程 ID谓词。 watchDog
然后取消所有正在运行的线程(全局oldest
维护仍然存活的最旧线程的ID以帮助它执行此操作),并退出程序。
// compile with: gcc -Wall -Wextra -Wconversion -pedantic -std=c99 -g -D_BSD_SOURCE -pthread -o pFiles pFiles.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <stdint.h>
#include "pthread.h"
#define INDIC_ALL_DONE_OK -1
typedef int_fast32_t int32;
typedef uint_fast32_t uint32;
uint32 MAXNBRTHREADS = 10; // no more than this amount of threads running in parallel
uint32 GROUPSIZE = 10; // how many files per thread
uint32 nbFiles, gThID; // total #files, group ID for a starting thread
int32 errIndc = 0; // global thread error indicator
pthread_t *thT; // pthread table
void **retVals; // thread ret. val. table, needed in stop_watchDog()
uint32 gThCnt; // calculated size of thT[]
uint32 thCnt, oldest; // running threads count (as they are created), oldest thread *alive*
pthread_cond_t errCv = PTHREAD_COND_INITIALIZER; // thread-originated error signal
pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER; // mutex to protect errIndc
// Worker thread
void *processFileGroup(void *arg) {
int32 err;
int last_state, last_type;
uint32 i, thId = (uint32)(intptr_t) arg;
fprintf(stderr, "th %ld started\n", thId);
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &last_state);
pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &last_type);
// Artificial error in thread 17
if(thId==17) {
pthread_mutex_lock(&mtx);
errIndc = (int32) thId;
pthread_cond_signal(&errCv);
pthread_mutex_unlock(&mtx);
pthread_exit((void *)(intptr_t)err); }
for(i = 0; i < GROUPSIZE ; i++) { // simulate processing GROUPSIZE files
pthread_testcancel();
err = 0;
if(usleep(10000)) { err = 1; break; }
}
//fprintf(stderr, " -- th %ld done with err = %ld\n", thId, err);
if(err!=0) { // Signal watch dog
pthread_mutex_lock(&mtx);
errIndc = (int32) thId;
pthread_cond_signal(&errCv);
pthread_mutex_unlock(&mtx);
pthread_exit((void *)(intptr_t) err);
}
pthread_exit((void *)(intptr_t) err);
}
// Mishap : cancel existing threads, exit program
int32 cancel_exit(int32 rc, int32 faultyThId, char *msg) {
uint32 j; int32 rval;
void *retVal;
if(rc==0) return 0;
if(msg!=NULL && msg[0]=='\0') fprintf(stderr, "\nError in thread %ld. Stoping..\n", faultyThId);
else fprintf(stderr, "\n%s %ld. Stop.\n\n", msg, faultyThId);
for(j = oldest; j < thCnt ; j++) pthread_cancel(thT[j]);
for(j = oldest; j < thCnt ; j++){
pthread_join(thT[j], &retVal); rval = (int)(intptr_t) retVal;
//if(retVal == PTHREAD_CANCELED || rval==115390242)
if(retVal == PTHREAD_CANCELED)
fprintf(stderr, " cexit: thread %ld canceled\n", j);
else fprintf(stderr, " cexit: thread %ld finished, rc = %ld\n", j, rval);
}
pthread_join(thT[4], &retVal); rval = (int)(intptr_t) retVal; fprintf(stderr, " cexit1: thread 4 finished, rc = %ld\n", rval);
fprintf(stderr, "Processing stopped\n\n");
exit(EXIT_FAILURE); return rc;
}
// Watch dog thread
// it fires on signal from one of the running threads about a mishap
void *watchDog(void *arg) {
int32 err;
pthread_mutex_lock(&mtx);
while (errIndc == 0) {
pthread_cond_wait(&errCv,&mtx);
if(errIndc == INDIC_ALL_DONE_OK){ // main() says we're done with no issues
pthread_mutex_unlock(&mtx);
err = 0; pthread_exit((void *)(intptr_t) err);
}
}
pthread_mutex_unlock(&mtx);
fprintf(stderr, "watch dog: stopping on error indication %ld\n", errIndc);
cancel_exit(1, errIndc, "");
exit(EXIT_FAILURE); return arg;// not reached
}
void stop_watchDog() {
pthread_mutex_lock(&mtx);
errIndc = INDIC_ALL_DONE_OK;
pthread_cond_signal(&errCv);
pthread_mutex_unlock(&mtx);
pthread_join(thT[0], &retVals[0]);
}
int main() {
uint32 i, k;
int32 rc;
nbFiles = 950;
gThCnt = 1+nbFiles/GROUPSIZE;
if(gThCnt > MAXNBRTHREADS)
fprintf(stderr, "running max %ld threads in parallel\n", MAXNBRTHREADS);
else fprintf(stderr, "using %ld worker thread(s)\n", gThCnt);
gThCnt++; // account for watchDog (thread 0)
thT = (pthread_t *) calloc(gThCnt, sizeof(pthread_t)); if(thT==NULL) { perror("calloc"); exit(EXIT_FAILURE); }
retVals = (void **) calloc( (nbFiles/GROUPSIZE), sizeof(void *)); if(retVals==NULL) { perror("calloc"); exit(EXIT_FAILURE); }
// Start watch dog
rc = pthread_create(&thT[0], NULL, watchDog, NULL);
if(rc != 0) { fprintf(stderr,"pthread_create() failed for thread 0\n"); exit(EXIT_FAILURE); }
thCnt = 1;
i = 0; oldest = 1;
while(thCnt<gThCnt) {
pthread_mutex_lock(&mtx);
if(errIndc != 0){ // watchDog is already tearing down the whole system, no point in creating more threads
pthread_join(thT[0], &retVals[0]); // wait on WatchDog thread, which never returns (it cancel_exists).
exit(EXIT_FAILURE); // not reached
}
pthread_mutex_unlock(&mtx);
gThID = thCnt;
rc = pthread_create(&thT[thCnt], NULL, processFileGroup, (void *)(intptr_t) gThID);
if(rc != 0) {
fprintf(stderr,"pthread_create() failed for thread %ld\n", thCnt);
stop_watchDog();
cancel_exit(1, (int32)thCnt, "Could not create thread");
}
thCnt++;
if(thCnt>MAXNBRTHREADS) { // wait for the oldest thread to finish
pthread_mutex_lock(&mtx);
if(errIndc != 0) { // watchDog is already tearing down the whole system, he'll report the rc of thread "oldest"
printf("[MAXNBRTHREADS] errIndc=%ld, joining watchDog\n", errIndc);
pthread_join(thT[0], &retVals[0]); // wait on WatchDog thread, which never returns (it cancel_exists).
exit(EXIT_FAILURE); // not reached
}
pthread_mutex_unlock(&mtx);
pthread_join(thT[oldest], &retVals[oldest]); rc = (int)(intptr_t) retVals[oldest];
fprintf(stderr, "[MAXNBRTHREADS] Thread %ld done with rc = %ld\n", oldest, rc);
oldest++;
}
}
k = oldest;
while(k<thCnt) {
pthread_mutex_lock(&mtx);
if(errIndc != 0){ // watchDog is already tearing down the whole system, he'll report the rc of thread k
pthread_join(thT[0], &retVals[0]); // wait on WatchDog thread, which never returns (it cancel_exists).
exit(EXIT_FAILURE); // not reached
}
pthread_mutex_unlock(&mtx);
pthread_join(thT[k], &retVals[k]); rc = (int)(intptr_t) retVals[k];
fprintf(stderr, "Thread %ld done with rc = %ld\n", k, rc);
oldest = ++k;
}
// Signal watch dog to quit
stop_watchDog();
exit(EXIT_SUCCESS);
}
第 82 行导致该程序出现段错误。为什么 ?加入已取消的线程是否违法?
如果您注释第 82 行,则会出现其他问题。如果您运行该程序 4 次中的 3 次,您会看到以下病理结果之一:
线程 11 怎么会有两个不同的退出代码?
..
watch dog: stopping on error indication 17
Error in thread 17. Stoping..
th 19 started
cexit: thread 11 finished, rc = 115390242
[MAXNBRTHREADS] Thread 11 done with rc = -1
有时程序会卡在 MAXNBRTHREADS 部分:
...
[MAXNBRTHREADS] errIndc=17, joining watchDog
这部分显然存在竞争条件;但我无法弄清楚。
感谢任何帮助。
最佳答案
你问:
Line 82 causes this program to segfault. Why ? Is it illegal to join a canceled thread ?
POSIX 并没有用那么多话来表达这一点,但它似乎确实暗示了这一点。 The specifications for pthread_join()
说:
The behavior is undefined if the value specified by the thread argument to pthread_join() does not refer to a joinable thread.
随后在基本原理中,
If an implementation detects use of a thread ID after the end of its lifetime, it is recommended that the function should fail and report an [ESRCH] error.
您观察到的段错误与基本原理中的(非规范)建议不一致,但基本原理确实支持线程在其生命周期结束后不再是“可连接线程”的主张(例如,因为它有已取消),否则建议将与函数指定的行为不一致。当然,已经加入的线程不再是可加入的,尽管使用“可加入”而不是“事件”或类似的原因可能更多是为了分离线程的规定。
How can thread 11 have two different exit codes ?
它不能,并且您的输出不会显示其他情况。您将加入线程 11 两次,因此至少其中一次 pthread_join()
调用必须失败。如果确实如此,您不能依赖它可能存储的任何结果值(无论如何,不基于 POSIX)。您应该检查函数调用的返回值是否有错误标志。
Sometimes the program will hang in MAXNBRTHREADS section
是的,看起来确实可以。
这里的想法似乎是,在失败的情况下,主线程将调用 stop_watchDog()
,它将设置一个标志来建议看门狗线程应该停止,然后向条件变量使看门狗醒来并注意到它。当它唤醒时,看门狗线程必须重新获取互斥量 mtx
,然后才能从 pthread_cond_wait()
返回。
从stop_watchDog()
返回后,主线程锁定互斥体mtx
并尝试加入看门狗线程。但发送简历并不是同步的。因此,主线程有可能在看门狗线程重新获取互斥锁之前锁定该互斥锁,在这种情况下,您将陷入死锁:看门狗无法从 pthread_cond_wait() 返回并继续终止,直到它获取互斥锁。但主线程不会解锁互斥体,直到看门狗终止。
我还没有对程序进行足够的分析,无法确定主线程需要保护的确切状态,尽管它似乎至少包含 errIndc
变量。然而,无论如何,它似乎不需要在尝试加入看门狗线程时保持互斥体锁定。
关于c - pthread_join() 中的段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46832246/
我想做的是让 JTextPane 在 JPanel 中占用尽可能多的空间。对于我使用的 UpdateInfoPanel: public class UpdateInfoPanel extends JP
我在 JPanel 中有一个 JTextArea,我想将其与 JScrollPane 一起使用。我正在使用 GridBagLayout。当我运行它时,框架似乎为 JScrollPane 腾出了空间,但
我想在 xcode 中实现以下功能。 我有一个 View Controller 。在这个 UIViewController 中,我有一个 UITabBar。它们下面是一个 UIView。将 UITab
有谁知道Firebird 2.5有没有类似于SQL中“STUFF”函数的功能? 我有一个包含父用户记录的表,另一个表包含与父相关的子用户记录。我希望能够提取用户拥有的“ROLES”的逗号分隔字符串,而
我想使用 JSON 作为 mirth channel 的输入和输出,例如详细信息保存在数据库中或创建 HL7 消息。 简而言之,输入为 JSON 解析它并输出为任何格式。 最佳答案 var objec
通常我会使用 R 并执行 merge.by,但这个文件似乎太大了,部门中的任何一台计算机都无法处理它! (任何从事遗传学工作的人的附加信息)本质上,插补似乎删除了 snp ID 的 rs 数字,我只剩
我有一个以前可能被问过的问题,但我很难找到正确的描述。我希望有人能帮助我。 在下面的代码中,我设置了varprice,我想添加javascript变量accu_id以通过rails在我的数据库中查找记
我有一个简单的 SVG 文件,在 Firefox 中可以正常查看 - 它的一些包装文本使用 foreignObject 包含一些 HTML - 文本包装在 div 中:
所以我正在为学校编写一个 Ruby 程序,如果某个值是 1 或 3,则将 bool 值更改为 true,如果是 0 或 2,则更改为 false。由于我有 Java 背景,所以我认为这段代码应该有效:
我做了什么: 我在这些账户之间创建了 VPC 对等连接 互联网网关也连接到每个 VPC 还配置了路由表(以允许来自双方的流量) 情况1: 当这两个 VPC 在同一个账户中时,我成功测试了从另一个 La
我有一个名为 contacts 的表: user_id contact_id 10294 10295 10294 10293 10293 10294 102
我正在使用 Magento 中的新模板。为避免重复代码,我想为每个产品预览使用相同的子模板。 特别是我做了这样一个展示: $products = Mage::getModel('catalog/pro
“for”是否总是检查协议(protocol)中定义的每个函数中第一个参数的类型? 编辑(改写): 当协议(protocol)方法只有一个参数时,根据该单个参数的类型(直接或任意)找到实现。当协议(p
我想从我的 PHP 代码中调用 JavaScript 函数。我通过使用以下方法实现了这一点: echo ' drawChart($id); '; 这工作正常,但我想从我的 PHP 代码中获取数据,我使
这个问题已经有答案了: Event binding on dynamically created elements? (23 个回答) 已关闭 5 年前。 我有一个动态表单,我想在其中附加一些其他 h
我正在尝试找到一种解决方案,以在 componentDidMount 中的映射项上使用 setState。 我正在使用 GraphQL连同 Gatsby返回许多 data 项目,但要求在特定的 pat
我在 ScrollView 中有一个 View 。只要用户按住该 View ,我想每 80 毫秒调用一次方法。这是我已经实现的: final Runnable vibrate = new Runnab
我用 jni 开发了一个 android 应用程序。我在 GetStringUTFChars 的 dvmDecodeIndirectRef 中得到了一个 dvmabort。我只中止了一次。 为什么会这
当我到达我的 Activity 时,我调用 FragmentPagerAdapter 来处理我的不同选项卡。在我的一个选项卡中,我想显示一个 RecyclerView,但他从未出现过,有了断点,我看到
当我按下 Activity 中的按钮时,会弹出一个 DialogFragment。在对话框 fragment 中,有一个看起来像普通 ListView 的 RecyclerView。 我想要的行为是当
我是一名优秀的程序员,十分优秀!