1

次のコードがあります(無関係な部分をいくつか削除しました)

このコードを使用すると、「connect_ip」からのスレッドが再び開始されないようにすることができますが、現在のスレッドはまだ実行されているため、それらも停止したいと思います (「connect_ip」のスレッドのみ)。

struct domain_list {
    char domain[20];
    struct domain_list * next;
};
typedef struct arg_struct {
    unsigned long ip;
    char domain[30];
    int X;
    int stop;
}arg_struct;
struct domain_list * first_domain = NULL;

int main()
{
    //loading into structure from file code is missing


    for(i = 0 ; i < number_thread; i++)
    {
        if(pthread_create(&thread_id[i],NULL,&start,NULL) != 0)
        {
            i--;
            fprintf(stderr,RED "\nError in creating thread\n" NONE);
        }
    }
    for(i = 0 ; i < number_thread; i++)
        if(pthread_join(thread_id[i],NULL) != 0)
        {
            fprintf(stderr,RED "\nError in joining thread\n" NONE);
        }
}


void * start(void * data)
{
    unsigned long ip = 0xffffffff;
    char ip[20];
    while (!feof(INFILE))
    {
        if (fgets(ip,sizeof(ip),INFILE) != NULL)
        {
            if (strlen(ip) < 8)
                break;
            if (ip[strlen (ip) - 1] == '\n')
                ip[strlen (ip) - 1] = '\0';
            ip = ntohl((unsigned long)inet_addr(ip));
        }
        connect_ip(ip);
    }
    return NULL;
}


void connect_ip(unsigned long ip)
{
    struct domain_list * curr_domain = first_domain;
    int exit=0,stop=0;
    while(curr_domain)
    {
        for(t = 0 ; t < ip_thread; t++)
        {
            pthread_mutex_lock(&thrd_list);
            arg_struct *args = calloc(1, sizeof(*args));
            strncpy(args->domain,curr_domain->domain,sizeof(args->domain) - 1);
            args->ip = ip;
            args->X = ex;
            args->stop = stop;
            pthread_mutex_unlock(&thrd_list);
            if(pthread_create(&thread_id[t],NULL,checkip,args) != 0)
            {
                t--;
                fprintf(stderr,RED "\nError in creating thread\n" NONE);
            }
            else
            {
                pthread_mutex_lock(&thrd_list);
                if(curr_domain->next != NULL)
                    curr_domain = curr_domain->next;
                else
                    exit = 1;
                pthread_mutex_unlock(&thrd_list);
            }
        }

        for(t = 0 ; t < ip_thread; t++)
        {
            void *join_result;
            if(pthread_join(thread_id[t],&join_result) != 0)
            {
                fprintf(stderr,RED "\nError in joining thread\n" NONE);
            }
            else
            {
                arg_struct *args = join_result;
                stop = args->stop;
                free(args);
            }
        }
        if (exit == 1 || stop == 1)
            break;
    }//end while

}

void *checkip(void *arguments)
{
    arg_struct *args = arguments;
    if (args->X == 1)
        return args;
    int sock = 0,ex = 0,ret = 0;
    struct in_addr t_in;
    t_in.s_addr = ntohl(args->ip);
    sock = check_port(args->ip,80);
    if(sock == -1)
    {
        args->X = 1;
        return args;
    }

//some code missing

    if(ret == 1)
        args->stop = 1;
    return args;
}

最初の質問は、void "checkip" で ret = 1 のときに "connect_ip" からのすべてのスレッドを停止し、"start" void からの他のスレッドに影響を与えないようにする方法です。

2 番目の質問は、この場合に pthread_mutex_lock を正しく使用して、「start」からのスレッドと「connect_ip」からのスレッドがデータを台無しにする方法です。

4

1 に答える 1

1

2 つの簡単な観察。まず、なぜ for ループでこれを行うのですか: "i--;"。このため、スレッド ID は、thread_id 配列内の異なるインデックスにある可能性があります。第二に、「t--;」と同じこと connect_ip() 関数で。これにより、pthread_join() の実行時に pthread_join() が誤ったスレッド ID を参照する可能性があります。

コメントで追加のテキストを探してください。

個々の connect_Ip スレッドがその子スレッド間で共通のシグナル変数を維持できるようにする簡単な例を追加します。この例では、connect_ip スレッドのグローバル変数を人為的にインデックス 1 に設定しています。このようにして、シグナルが設定されると、connect_ip スレッドのすべての (3 つの) 子スレッドが停止します。一方、もう一方の親スレッド (インデックス 0 の connect_ip) は引き続き実行されます。

#include <stdio.h>
#include <pthread.h>

#define TEMP_MAX_THREADS 2
#define TEMP_MAX_CHILD_THREADS 3

int stop[TEMP_MAX_THREADS];

typedef struct two_ints_ {
    int parent_index;
    int child_index;
    int *common_stop_all_children;
} two_ints;

void *check_ip (void *arg) {
    int i = 0, temp;
    two_ints *x = (two_ints *)arg;
    printf("\t%s Starting to run (index: %d parent: %d) \n",
            __FUNCTION__, x->child_index, x->parent_index);
    srand(time(NULL));
    while (i++ < 10){
        printf("\t%s Me wokeup (index: %d parent: %d) \n",
                __FUNCTION__, x->child_index, x->parent_index);
        sleep(1);
        if (x->parent_index == 1) {
            if (*(x->common_stop_all_children) == 1) {
                printf("\t%s Other thread has set the stop signal (index: %d parent: %d). Return\n",
                        __FUNCTION__, x->child_index, x->parent_index);
                return;
            }
            temp = rand() % 4;
            if (temp == 2) {
                printf("\t%s Time to return. Let us set the global stop to 1 (index: %d parent: %d) \n",
                        __FUNCTION__, x->child_index, x->parent_index);
                *(x->common_stop_all_children) = 1;
                return;
            }
        }
    }
    return NULL;
}

void *connect_ip (void *arg) {
    int common_stop_all_children = 0;
    pthread_t child_thread_id[TEMP_MAX_CHILD_THREADS];
    two_ints arg_two_ints[TEMP_MAX_CHILD_THREADS];
    int i;

    printf("I am here with index: %d \n", *(int *)arg);
    for(i = 0 ; i < TEMP_MAX_CHILD_THREADS; i++) {
        arg_two_ints[i].parent_index = *(int *)arg;
        arg_two_ints[i].child_index = i;
        arg_two_ints[i].common_stop_all_children = &common_stop_all_children;

        if(pthread_create(&child_thread_id[i], NULL, check_ip, (void*) &arg_two_ints[i]) != 0) {
            fprintf(stderr, "\nError in creating thread\n" );
        }
    }

    for(i = 0 ; i < TEMP_MAX_CHILD_THREADS; i++) {
        if(pthread_join(child_thread_id[i], NULL) != 0) {
            fprintf(stderr, "\npthread_join failed\n" );
        }
    }

    return NULL;
}

int main() {
    pthread_t thread_id[TEMP_MAX_THREADS];
    int index[TEMP_MAX_THREADS];
    int i;

    for(i = 0 ; i < TEMP_MAX_THREADS; i++) {
        index[i] = i;
        if(pthread_create(&thread_id[i], NULL, connect_ip, (void *)&index[i]) != 0) {
            fprintf(stderr, "\nError in creating thread\n" );
        }
    }

    for(i = 0 ; i < TEMP_MAX_THREADS; i++) {
        if(pthread_join(thread_id[i], NULL) != 0) {
            fprintf(stderr, "\npthread_join failed\n");
        }
    }

}

出力例を次に示します。

$ ./a.out
I am here with index: 1
I am here with index: 0
    check_ip Starting to run (index: 0 parent: 1)
    check_ip Starting to run (index: 1 parent: 1)
    check_ip Me wokeup (index: 0 parent: 1)
    check_ip Starting to run (index: 0 parent: 0)
    check_ip Starting to run (index: 2 parent: 1)
    check_ip Me wokeup (index: 1 parent: 1)
    check_ip Starting to run (index: 1 parent: 0)
    check_ip Starting to run (index: 2 parent: 0)
    check_ip Me wokeup (index: 0 parent: 0)
    check_ip Me wokeup (index: 2 parent: 1)
    check_ip Me wokeup (index: 1 parent: 0)
    check_ip Me wokeup (index: 2 parent: 0)
    check_ip Me wokeup (index: 2 parent: 1)
    check_ip Me wokeup (index: 0 parent: 0)
    check_ip Time to return. Let us set the global stop to 1 (index: 1 parent: 1)
    check_ip Me wokeup (index: 1 parent: 0)
    check_ip Me wokeup (index: 2 parent: 0)
    check_ip Me wokeup (index: 0 parent: 1)
    check_ip Me wokeup (index: 2 parent: 0)
    check_ip Other thread has set the stop signal (index: 2 parent: 1). Return
    check_ip Me wokeup (index: 0 parent: 0)
    check_ip Me wokeup (index: 1 parent: 0)
    check_ip Other thread has set the stop signal (index: 0 parent: 1). Return
    check_ip Me wokeup (index: 2 parent: 0)
    check_ip Me wokeup (index: 0 parent: 0)
    check_ip Me wokeup (index: 1 parent: 0)
    check_ip Me wokeup (index: 1 parent: 0)
    check_ip Me wokeup (index: 0 parent: 0)
    check_ip Me wokeup (index: 2 parent: 0)
    check_ip Me wokeup (index: 2 parent: 0)
    check_ip Me wokeup (index: 1 parent: 0)
    check_ip Me wokeup (index: 0 parent: 0)
    check_ip Me wokeup (index: 2 parent: 0)
    check_ip Me wokeup (index: 0 parent: 0)
    check_ip Me wokeup (index: 1 parent: 0)
    check_ip Me wokeup (index: 2 parent: 0)
    check_ip Me wokeup (index: 1 parent: 0)
    check_ip Me wokeup (index: 0 parent: 0)
^C
于 2013-09-17T17:22:50.413 に答える