~cyphermox/ubuntu/trusty/multipath-tools/usb+local

« back to all changes in this revision

Viewing changes to libmultipath/waiter.c

  • Committer: Package Import Robot
  • Author(s): Rafael David Tinoco
  • Date: 2014-08-07 16:15:25 UTC
  • Revision ID: package-import@ubuntu.com-20140807161525-whfb9ggygzcwuawa
Tags: 0.4.9-3ubuntu7.1
* Added 0011-libmultipath-update-waiter-handling.patch (LP: #1354114)
* Added 0012-Race-condition-when-calling-stop_waiter_thread.patch (LP: #1354114)
* Added 0013-multipath-clean-up-code-for-stopping-the-waiter-thre.patch (LP: #1354114)
* Added 0014-Fix-race-condition-in-stop_waiter_thread.patch (LP: #1354114)

Show diffs side-by-side

added added

removed removed

Lines of Context:
28
28
        struct event_thread *wp;
29
29
 
30
30
        wp = (struct event_thread *)MALLOC(sizeof(struct event_thread));
 
31
        memset(wp, 0, sizeof(struct event_thread));
31
32
 
32
33
        return wp;
33
34
}
34
35
 
35
36
void free_waiter (void *data)
36
37
{
37
 
        sigset_t old;
38
38
        struct event_thread *wp = (struct event_thread *)data;
39
39
 
40
 
        /*
41
 
         * indicate in mpp that the wp is already freed storage
42
 
         */
43
 
        block_signal(SIGHUP, &old);
44
 
        lock(wp->vecs->lock);
45
 
 
46
 
        if (wp->mpp)
47
 
                /*
48
 
                 * be careful, mpp may already be freed -- null if so
49
 
                 */
50
 
                wp->mpp->waiter = NULL;
51
 
        else
52
 
                /*
53
 
                * This is OK condition during shutdown.
54
 
                */
55
 
                condlog(3, "free_waiter, mpp freed before wp=%p (%s).", wp, wp->mapname);
56
 
 
57
 
        unlock(wp->vecs->lock);
58
 
        pthread_sigmask(SIG_SETMASK, &old, NULL);
59
 
 
60
40
        if (wp->dmt)
61
41
                dm_task_destroy(wp->dmt);
62
42
 
65
45
 
66
46
void stop_waiter_thread (struct multipath *mpp, struct vectors *vecs)
67
47
{
68
 
        struct event_thread *wp = (struct event_thread *)mpp->waiter;
69
48
        pthread_t thread;
70
49
 
71
 
        if (!wp) {
72
 
                condlog(3, "%s: no waiter thread", mpp->alias);
 
50
        if (mpp->waiter == (pthread_t)0) {
 
51
                condlog(3, "%s: event checker thread already stopped",
 
52
                        mpp->alias);
73
53
                return;
74
54
        }
75
 
        thread = wp->thread;
76
 
        condlog(2, "%s: stop event checker thread (%lu)", wp->mapname, thread);
77
 
 
78
 
        pthread_kill(thread, SIGUSR1);
79
 
}
80
 
 
81
 
static sigset_t unblock_signals(void)
82
 
{
83
 
        sigset_t set, old;
84
 
 
85
 
        sigemptyset(&set);
86
 
        sigaddset(&set, SIGHUP);
87
 
        sigaddset(&set, SIGUSR1);
88
 
        pthread_sigmask(SIG_UNBLOCK, &set, &old);
89
 
        return old;
 
55
        condlog(2, "%s: stop event checker thread (%lu)", mpp->alias,
 
56
                mpp->waiter);
 
57
        thread = mpp->waiter;
 
58
        mpp->waiter = (pthread_t)0;
 
59
        pthread_cancel(thread);
90
60
}
91
61
 
92
62
/*
95
65
 */
96
66
int waiteventloop (struct event_thread *waiter)
97
67
{
98
 
        sigset_t set;
99
68
        int event_nr;
100
69
        int r;
101
70
 
112
81
                condlog(0, "%s: devmap event #%i dm_task_set_name error",
113
82
                                waiter->mapname, waiter->event_nr);
114
83
                dm_task_destroy(waiter->dmt);
 
84
                waiter->dmt = NULL;
115
85
                return 1;
116
86
        }
117
87
 
120
90
                condlog(0, "%s: devmap event #%i dm_task_set_event_nr error",
121
91
                                waiter->mapname, waiter->event_nr);
122
92
                dm_task_destroy(waiter->dmt);
 
93
                waiter->dmt = NULL;
123
94
                return 1;
124
95
        }
125
96
 
126
97
        dm_task_no_open_count(waiter->dmt);
127
98
 
128
 
        /* accept wait interruption */
129
 
        set = unblock_signals();
130
 
 
131
99
        /* wait */
132
100
        r = dm_task_run(waiter->dmt);
133
101
 
134
 
        /* wait is over : event or interrupt */
135
 
        pthread_sigmask(SIG_SETMASK, &set, NULL);
136
 
 
137
 
        if (!r) /* wait interrupted by signal */
138
 
                return -1;
139
 
 
140
102
        dm_task_destroy(waiter->dmt);
141
103
        waiter->dmt = NULL;
 
104
 
 
105
        if (!r) /* wait interrupted by signal */
 
106
                return -1;
 
107
 
142
108
        waiter->event_nr++;
143
109
 
144
110
        /*
217
183
        if (!wp)
218
184
                goto out;
219
185
 
220
 
        mpp->waiter = (void *)wp;
221
186
        strncpy(wp->mapname, mpp->alias, WWID_SIZE);
222
187
        wp->vecs = vecs;
223
 
        wp->mpp = mpp;
224
188
 
225
189
        if (pthread_create(&wp->thread, &waiter_attr, waitevent, wp)) {
226
190
                condlog(0, "%s: cannot create event checker", wp->mapname);
227
191
                goto out1;
228
192
        }
 
193
        mpp->waiter = wp->thread;
229
194
        condlog(2, "%s: event checker started", wp->mapname);
230
195
 
231
196
        return 0;
232
197
out1:
233
198
        free_waiter(wp);
234
 
        mpp->waiter = NULL;
 
199
        mpp->waiter = (pthread_t)0;
235
200
out:
236
201
        condlog(0, "failed to start waiter thread");
237
202
        return 1;