PTHREAD_CANCEL_ASYNCHRONOUS取消整个过程

Cod*_*ode 4 c multithreading pthreads

在C程序中,PTHREAD_CANCEL_ASYNCHRONOUS只要从父线程触发pthread_cancel ,我就会立即取消该线程.但它导致整个过程因Segmentation Fault而崩溃.子线程的工作是从数据库服务器获取一些数据.我的逻辑是,如果它在10秒内没有获取数据,那么该线程应该从父线程中被杀死.

我只想杀死子线程,而不是整个过程.

struct str_thrd_data
{
        SQLHANDLE hstmt;
        int rc;
        bool thrd_completed_flag;
};


void * str_in_thread_call(void *in_str_arg)
{
        int thrd_rc;
        struct str_thrd_data *str_arg;
        str_arg = in_str_arg;

        thrd_rc = pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
        if (thrd_rc != 0)
               handle_error_en(thrd_rc, "pthread_setcancelstate");

        thrd_rc = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
        if (thrd_rc != 0)
               handle_error_en(thrd_rc, "pthread_setcancelstate");

        thrd_rc = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
        if (thrd_rc != 0)
               handle_error_en(thrd_rc, "pthread_setcanceltype");
        // Code to call SQL Dynamic Query from a Database Server. This takes time more than 10 seconds.
      thrd_rc = SQLExecute(hstmt);
        printf("\n*********************Normal Thread termination withing timelimit %d\n",str_arg->rc);
        str_arg->thrd_completed_flag = true;

}

int main()
{
        printf("\nPJH: New THread created.\n");
        pthread_attr_t tattr;
        pthread_t th;
        size_t mysize = 1;

        struct str_thrd_data atd;

        atd.hstmt = hstmt;
        atd.rc= rc;
        atd.thrd_completed_flag = false;

        thrd_rc = pthread_attr_init(&tattr);
        thrd_rc = pthread_attr_setstacksize(&tattr, mysize);
        thrd_rc = pthread_create(&th, &tattr, &str_in_thread_call, &atd);
        if (thrd_rc != 0)
               handle_error_en(thrd_rc, "pthread_create");

        // While Loop tp count till 10 seconds.
        while(timeout !=0)
        {
                printf("%d Value of rc=%d\n",timeout, atd.rc);
                if(atd.rc != 999) break;
                timeout--;
                usleep(10000);
        }
        rc = atd.rc;
        //Condition to check if thread is completed or not yet.
          if(atd.thrd_completed_flag == false)
        {
                //Thread not comepleted within time, so Kill it now.
                printf("PJH ------- 10 Seconds Over\n");
                thrd_rc = pthread_cancel(th);
                printf("PJH ------- Thread Cancelled Immediately \n");    
                if (thrd_rc != 0)
                {
                       handle_error_en(thrd_rc, "pthread_cancel");
                }
                printf("\nPJH &&&&&&&& Thread Cancelled Manually\n");
        }
        thrd_rc = pthread_join(th,NULL);
        // some other job .....
}
Run Code Online (Sandbox Code Playgroud)

gdb process_name corefile 显示以下回溯: - 主要是所有SQL库函数.

#0  0xffffe410 in __kernel_vsyscall ()
#1  0x0059fe30 in raise () from /lib/libc.so.6
#2  0x005a1741 in abort () from /lib/libc.so.6
#3  0xdef3f5d7 in ?? () from /usr/lib/libstdc++.so.5
#4  0xdef3f624 in std::terminate() () from /usr/lib/libstdc++.so.5
#5  0xdef3f44c in __gxx_personality_v0 () from /usr/lib/libstdc++.so.5
#6  0x007e1917 in ?? () from /lib/libgcc_s.so.1
#7  0x007e1c70 in _Unwind_ForcedUnwind () from /lib/libgcc_s.so.1
#8  0x007cda46 in _Unwind_ForcedUnwind () from /lib/libpthread.so.0
#9  0x007cb471 in __pthread_unwind () from /lib/libpthread.so.0
#10 0x007c347a in sigcancel_handler () from /lib/libpthread.so.0
#11 <signal handler called>
#12 0xffffe410 in __kernel_vsyscall ()
#13 0x0064decb in semop () from /lib/libc.so.6
#14 0xe0245901 in sqloSSemP () from /opt/IBM/db2/V9.1/lib32/libdb2.so.1
#15 0xe01e7f3c in sqlccipcrecv(sqlcc_comhandle*, sqlcc_cond*) () from /opt/IBM/db2/V9.1/lib32/libdb2.so.1
#16 0xe03fe135 in sqlccrecv () from /opt/IBM/db2/V9.1/lib32/libdb2.so.1
#17 0xe02a0307 in sqljcReceive(sqljCmnMgr*) () from /opt/IBM/db2/V9.1/lib32/libdb2.so.1
#18 0xe02d0ba3 in sqljrReceive(sqljrDrdaArCb*, db2UCinterface*) () from /opt/IBM/db2/V9.1/lib32/libdb2.so.1
#19 0xe02c510d in sqljrDrdaArExecute(db2UCinterface*, UCstpInfo*) () from /opt/IBM/db2/V9.1/lib32/libdb2.so.1
#20 0xe01392bc in CLI_sqlCallProcedure(CLI_STATEMENTINFO*, CLI_ERRORHEADERINFO*) () from /opt/IBM/db2/V9.1/lib32/libdb2.so.1
#21 0xe00589c7 in SQLExecute2(CLI_STATEMENTINFO*, CLI_ERRORHEADERINFO*) () from /opt/IBM/db2/V9.1/lib32/libdb2.so.1
#22 0xe0050fc9 in SQLExecute () from /opt/IBM/db2/V9.1/lib32/libdb2.so.1
#23 0x080a81f7 in apcd_in_thread_call (in_apcd_arg=0xbc8e8f34) at dcs_db2_execute.c:357
#24 0x007c4912 in start_thread () from /lib/libpthread.so.0
#25 0x0064c60e in clone () from /lib/libc.so.6
Run Code Online (Sandbox Code Playgroud)

zwo*_*wol 8

异步线程取消只能在执行非常有限的操作集的线程上安全使用 - 官方规则很长且令人困惑,但实际上受异步取消影响的线程只能执行纯计算.他们不能做I/O,他们不能分配内存,他们不能采取任何类型的锁,他们不能调用任何可能执行上述任何功能的库函数. 将异步取消应用于与数据库通信的线程是不安全的.

延期取消受到的限制较少,但仍然非常挑剔.如果您的数据库库没有编码以应对调用线程可能在操作中被取消的可能性 - 而且可能不是 - 那么您也无法安全地使用延迟取消.

您需要找到一些其他机制来中止运行时间过长的查询.

编辑:由于这是DB2和容易混淆的"CLI"API,请尝试使用SqlSetStmtAttr在预SQL_ATTR_QUERY_TIMEOUT准备语句上设置参数. 这是可以设置的这样参数的完整列表,并在这里是查询超时的一些更多的讨论.

SON OF EDIT:根据一位比我更多的数据库工作的朋友说,很可能有一个服务器端机制来取消慢速查询,无论其来源如何.如果在DB2中存在这种情况,那么比在客户端的所有查询上手动设置超时可能更方便,特别是因为它可以记录慢速查询,以便您知道它们是哪些并且可以优化它们.