2011-11-01 57 views
0

完整的我居然問了類似的問題在前面,但Correct way to shutdown C application to ensure CRITICAL sections completed?想重新開始,問的是任何人都可以看到,並用下面的代碼根本問題。確保交易都在關閉掛鉤...示例代碼檢查

我本質上颳起了概念證明,它是這樣的:

  • 主要的應用程序啓動,需要「在交易過程中的信息」
  • 當用戶點擊CTRL-C到線程我需要的應用程序優雅,直到當前線程交易完成

注意運行:從線程進入主要的應用程序是必不可少的回調,我想知道這是否是「不好的編程習慣」 ......

的代碼是從輸出工作,這裏是一個示例:

[email protected] ~/Desktop/ThreadTest $ ./main 
Main program started 
In thread testMainLoop 
Transaction started in spawned thread 
onBeginTransaction in main thread 
onMessageArrived in main thread 
onCommitTransaction in main thread 
Transaction ended in spawned thread 
Transaction started in spawned thread 
onBeginTransaction in main thread 
onMessageArrived in main thread 
onCommitTransaction in main thread 
Transaction ended in spawned thread 
Transaction started in spawned thread 
onBeginTransaction in main thread 
onMessageArrived in main thread 
onCommitTransaction in main thread 
Transaction ended in spawned thread 
^CIn shutdown hook... 
Thread still running 
listenForMessages loop completed in spawned thread 
In onProcessingComplete in main thread 
Exciting testMainLoop 
All thread transactions complete 
Main program exiting 
[email protected] ~/Desktop/ThreadTest $ 

在上面你可以看到,關閉掛接啓動和應用程序優雅地結束...

基礎測試代碼如下:

請特別注意的 「(* onProcessingCompleteCallbackFunc)(TRUE);」從線程應用程序的主打電話說在主應用程序線程是100%完成。 pthread_join似乎不工作,因爲我需要它在這裏......

注意:以下是我創建的共享LIB(libwmq_sender.so),供主應用程序使用。

wmq_sender.h

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <time.h> 

#define TRUE 0 
#define FALSE 1 

int wmq_sender_start(); 
int wmq_sender_stop(); 
void wmq_sender_registerOnBeginTransactionCallback(int (*callbackFunc)(char *tid)); 
void wmq_sender_registerOnCommitTransactionCallback(int (*callbackFunc)(char *tid)); 
void wmq_sender_registerOnMessageArrivedCallback(int (*callbackFunc)(char *tid, char *buffer, int size)); 
void wmq_sender_registerOnProcessingCompleteCallback(void (*callbackFunc)(int completeFlag)); 
int listenForMessages(); 

int (*onBeginTransactionCallbackFunc)(char *tid); 
int (*onCommitTransactionCallbackFunc)(char *tid); 
int (*onRollbackTransactionCallbackFunc)(char *tid); 
int (*onMessageArrivedCallbackFunc)(char *tid, char *buffer, int size); 
void (*onProcessingCompleteCallbackFunc)(int completeFlag); 

int running; 
int rc; 
int transactionRunning; 

wmq_sender.c

#include "wmq_sender.h" 

int listenForMessages(){ 
    char *uuid = NULL;; 
    char *buffer = NULL; 
    uuid = malloc(10 * sizeof(char)); 
    strcpy(uuid, "1234567891"); 
    buffer = malloc(11 * sizeof(char)); 
    strcpy(buffer, "test_buffer"); 

    while(running == TRUE){ 
     printf("Transaction started in spawned thread\n"); 
     transactionRunning = TRUE; 
     (*onBeginTransactionCallbackFunc)(uuid); 
     (*onMessageArrivedCallbackFunc)(uuid, buffer, 11); 
     (*onCommitTransactionCallbackFunc)(uuid); 
     transactionRunning = FALSE; 
     printf("Transaction ended in spawned thread\n"); 
     sleep(2); 
    } 
    printf("listenForMessages loop completed in spawned thread\n"); 
    free(uuid); 
    free(buffer); 
    (*onProcessingCompleteCallbackFunc)(TRUE); 
    return 0; 
} 

int wmq_sender_start(){ 
    return listenForMessages(); 
} 

int wmq_sender_stop(){ 
    running = FALSE; 
    return 0; 
} 

void wmq_sender_registerOnBeginTransactionCallback(int (*callbackFunc)(char *tid)){ 
    onBeginTransactionCallbackFunc = callbackFunc; 
} 
void wmq_sender_registerOnCommitTransactionCallback(int (*callbackFunc)(char *tid)){ 
    onCommitTransactionCallbackFunc = callbackFunc; 
} 
void wmq_sender_registerOnMessageArrivedCallback(int (*callbackFunc)(char *tid, char *buffer, int size)){ 
    onMessageArrivedCallbackFunc = callbackFunc; 
} 
void wmq_sender_registerOnProcessingCompleteCallback(void (*callbackFunc)(int completeFlag)){ 
    onProcessingCompleteCallbackFunc = callbackFunc; 
} 

以下是主要的應用程序,它會生成線程和關閉勇退等

#include <stdio.h> 
#include <stdlib.h> 
#include <signal.h> 
#include <pthread.h> 
#include <time.h> 
#include "wmq_sender.h" 

#define TRUE 0 
#define FALSE 1 

void *testMainLoop(void *arg); 
void shutdownHook(int sig); 
int main(int argc, char * argv[]); 
int onBeginTransaction(char *tid); 
int onCommitTransaction(char *tid); 
int onMessageArrived(char *tid, char *buffer, int size); 
void onProcessingComplete(int completeFlag); 

pthread_t testThread; 
int threadRunning; 
int rc; 

void *testMainLoop(void *arg){ 
    printf("In thread testMainLoop\n"); 
    wmq_sender_registerOnBeginTransactionCallback(onBeginTransaction); 
    wmq_sender_registerOnCommitTransactionCallback(onCommitTransaction); 
    wmq_sender_registerOnMessageArrivedCallback(onMessageArrived); 
    wmq_sender_registerOnProcessingCompleteCallback(onProcessingComplete); 
    threadRunning = TRUE; 
    rc = wmq_sender_start(); 
    printf("Exciting testMainLoop\n"); 
} 

void shutdownHook(int sig){ 
    printf("In shutdown hook...\n"); 
    rc = wmq_sender_stop(); 
    while(threadRunning == TRUE){ 
     printf("Thread still running\n"); 
     sleep(2); 
    } 
    printf("All thread transactions complete\n"); 
} 

void onProcessingComplete(int completeFlag){ 
    printf("In onProcessingComplete in main thread\n"); 
    threadRunning = FALSE; 
} 

int main(int argc, char * argv[]){ 
    (void) signal(SIGINT, shutdownHook); 
    printf("Main program started\n"); 
    rc = pthread_create(&testThread, NULL, testMainLoop, (void *)argv); 
    pthread_join(testThread, NULL); 
    printf("Main program exiting\n"); 
    return 0; 
} 

int onBeginTransaction(char *tid){ 
    printf("onBeginTransaction in main thread\n"); 
    return 0; 
} 
int onCommitTransaction(char *tid){ 
    printf("onCommitTransaction in main thread\n"); 
    return 0; 
} 
int onMessageArrived(char *tid, char *buffer, int size){ 
    printf("onMessageArrived in main thread\n"); 
    return 0; 
} 

編譯我的試驗機是:

gcc -m64 -Wall -g -I./ -c ./main.c -o ./main.o 
gcc -m64 -o ./main ./main.o -L./ -L/usr/lib -L/usr/local/lib -lpthread -lwmq_sender 

gcc -m64 -Wall -g -c -I./ -I/usr/local/include/ -fPIC ./wmq_sender.c -o ./wmq_sender.o 
gcc -shared -o ./libwmq_sender.so ./wmq_sender.o 

export LD_LIBRARY_PATH="/home/lynton/Desktop/ThreadTest" 

你看到什麼不對,我使用回調告訴主應用程序線程完成等方式?

任何幫助或提醒將是巨大的讚賞;-)

感謝

林頓

回答

1

你一定要明白,你的回調函數實際上是線程上運行的不好嗎?據我所看到的,你的主線程只是創建另一個線程該做的一切,然後等待它完成。目前我沒有看到創建第二個線程的任何問題。

無論如何,你有另一個可怕的問題是你的信號處理程序調用printfsleep。我很確定printf在信號處理程序中調用並不安全,也不是sleep。真的,它應該做的就是設置一個標誌來說「終止」,然後返回。

按照C99標準,你不能可靠地分配給未聲明volatile sig_atomic_t任何靜態變量或調用任何標準庫函數,除了abort()_Exit()signal(),最後與您收到相同數量信號。