gpt4 book ai didi

c - 确保事务在 SHUTDOWN Hook 上全部完成...示例代码检查

转载 作者:行者123 更新时间:2023-11-30 16:00:14 25 4
gpt4 key购买 nike

实际上,我之前在 Correct way to shutdown C application to ensure CRITICAL sections completed? 上问过类似的问题,但想重新开始,问是否任何人都可以看到以下代码的基本问题。

我基本上提出了一个概念证明,它是这样的:

  • 主应用程序启动一个需要“处理事务中的消息”的线程
  • 当用户按下 CTRL-C 时,我需要应用程序优雅地运行,直到当前线程事务完成

注意:从线程到主应用程序的回调是必不可少的,我想知道这是否是“糟糕的编程实践”....

代码正在根据输出运行,这里是一个示例:

lynton@lynton ~/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
lynton@lynton ~/Desktop/ThreadTest $

在上面你可以看到关闭钩子(Hook)被启动并且应用程序优雅地结束......

基础测试代码如下:

请特别注意“(*onProcessingCompleteCallbackFunc)(TRUE);”从线程调用主应用程序,告诉主应用程序该线程已 100% 完成。 pthread_join 似乎无法正常工作,因为我需要它在这里......

注意:以下是我创建的主应用程序使用的共享库 (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"

您认为我使用 CALLBACKS 告诉主应用程序线程已完成等的方式有什么问题吗?

任何帮助或建议将不胜感激;-)

谢谢

林顿

最佳答案

您确实意识到您的回调函数实际上是在线程上运行的,不是吗?据我所见,您的主线程只是创建另一个线程来完成所有操作,然后等待它完成。我认为目前创建第二个线程没有任何意义。

无论如何,您遇到的另一个可怕的问题是您的信号处理程序调用 printfsleep。我非常确定在信号处理程序中调用 printf 并不安全,sleep 也不安全。实际上它应该做的就是设置一个标志来表示“终止”,然后返回。

根据 C99 标准,您无法可靠地分配给任何未声明为 volatile sig_atomic_t 的静态变量,也无法调用除 abort() 之外的任何标准库函数、_Exit()signal() 以及最后一个与您收到的信号编号相同的信号。

关于c - 确保事务在 SHUTDOWN Hook 上全部完成...示例代码检查,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7965696/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com