~ubuntu-branches/ubuntu/natty/clamav/natty-security

« back to all changes in this revision

Viewing changes to win32/3rdparty/pthreads/ptw32_callUserDestroyRoutines.c

  • Committer: Bazaar Package Importer
  • Author(s): Scott Kitterman
  • Date: 2011-02-19 09:51:33 UTC
  • mfrom: (0.35.19 sid)
  • Revision ID: james.westby@ubuntu.com-20110219095133-sde2dyj8a6bjbkdh
Tags: 0.97+dfsg-0ubuntu1
* Merge from debian unstable (0ubuntu1 because the Debian upload was
  inadvertently left marked UNRELEASED).  Remaining changes:
  - Drop initial signature definitions from clamav-base
  - Drop build-dep on electric-fence (in Universe)
  - Add apparmor profiles for clamd and freshclam along with maintainer
    script changes

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * ptw32_callUserDestroyRoutines.c
 
3
 *
 
4
 * Description:
 
5
 * This translation unit implements routines which are private to
 
6
 * the implementation and may be used throughout it.
 
7
 *
 
8
 * --------------------------------------------------------------------------
 
9
 *
 
10
 *      Pthreads-win32 - POSIX Threads Library for Win32
 
11
 *      Copyright(C) 1998 John E. Bossom
 
12
 *      Copyright(C) 1999,2005 Pthreads-win32 contributors
 
13
 * 
 
14
 *      Contact Email: rpj@callisto.canberra.edu.au
 
15
 * 
 
16
 *      The current list of contributors is contained
 
17
 *      in the file CONTRIBUTORS included with the source
 
18
 *      code distribution. The list can also be seen at the
 
19
 *      following World Wide Web location:
 
20
 *      http://sources.redhat.com/pthreads-win32/contributors.html
 
21
 * 
 
22
 *      This library is free software; you can redistribute it and/or
 
23
 *      modify it under the terms of the GNU Lesser General Public
 
24
 *      License as published by the Free Software Foundation; either
 
25
 *      version 2 of the License, or (at your option) any later version.
 
26
 * 
 
27
 *      This library is distributed in the hope that it will be useful,
 
28
 *      but WITHOUT ANY WARRANTY; without even the implied warranty of
 
29
 *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
30
 *      Lesser General Public License for more details.
 
31
 * 
 
32
 *      You should have received a copy of the GNU Lesser General Public
 
33
 *      License along with this library in the file COPYING.LIB;
 
34
 *      if not, write to the Free Software Foundation, Inc.,
 
35
 *      59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
 
36
 */
 
37
 
 
38
#include "pthread.h"
 
39
#include "implement.h"
 
40
 
 
41
#ifdef __cplusplus
 
42
# if ! defined (_MSC_VER) && ! (defined(__GNUC__) && __GNUC__ < 3) && ! defined(__WATCOMC__)
 
43
using
 
44
  std::terminate;
 
45
# endif
 
46
#endif
 
47
 
 
48
void
 
49
ptw32_callUserDestroyRoutines (pthread_t thread)
 
50
     /*
 
51
      * -------------------------------------------------------------------
 
52
      * DOCPRIVATE
 
53
      *
 
54
      * This the routine runs through all thread keys and calls
 
55
      * the destroy routines on the user's data for the current thread.
 
56
      * It simulates the behaviour of POSIX Threads.
 
57
      *
 
58
      * PARAMETERS
 
59
      *              thread
 
60
      *                      an instance of pthread_t
 
61
      *
 
62
      * RETURNS
 
63
      *              N/A
 
64
      * -------------------------------------------------------------------
 
65
      */
 
66
{
 
67
  ThreadKeyAssoc * assoc;
 
68
 
 
69
  if (thread.p != NULL)
 
70
    {
 
71
      int assocsRemaining;
 
72
      int iterations = 0;
 
73
      ptw32_thread_t * sp = (ptw32_thread_t *) thread.p;
 
74
 
 
75
      /*
 
76
       * Run through all Thread<-->Key associations
 
77
       * for the current thread.
 
78
       *
 
79
       * Do this process at most PTHREAD_DESTRUCTOR_ITERATIONS times.
 
80
       */
 
81
      do
 
82
        {
 
83
          assocsRemaining = 0;
 
84
          iterations++;
 
85
 
 
86
          (void) pthread_mutex_lock(&(sp->threadLock));
 
87
          /*
 
88
           * The pointer to the next assoc is stored in the thread struct so that
 
89
           * the assoc destructor in pthread_key_delete can adjust it
 
90
           * if it deletes this assoc. This can happen if we fail to acquire
 
91
           * both locks below, and are forced to release all of our locks,
 
92
           * leaving open the opportunity for pthread_key_delete to get in
 
93
           * before us.
 
94
           */
 
95
          sp->nextAssoc = sp->keys;
 
96
          (void) pthread_mutex_unlock(&(sp->threadLock));
 
97
 
 
98
          for (;;)
 
99
            {
 
100
              void * value;
 
101
              pthread_key_t k;
 
102
              void (*destructor) (void *);
 
103
 
 
104
              /*
 
105
               * First we need to serialise with pthread_key_delete by locking
 
106
               * both assoc guards, but in the reverse order to our convention,
 
107
               * so we must be careful to avoid deadlock.
 
108
               */
 
109
              (void) pthread_mutex_lock(&(sp->threadLock));
 
110
 
 
111
              if ((assoc = (ThreadKeyAssoc *)sp->nextAssoc) == NULL)
 
112
                {
 
113
                  /* Finished */
 
114
                  pthread_mutex_unlock(&(sp->threadLock));
 
115
                  break;
 
116
                }
 
117
              else
 
118
                {
 
119
                  /*
 
120
                   * assoc->key must be valid because assoc can't change or be
 
121
                   * removed from our chain while we hold at least one lock. If
 
122
                   * the assoc was on our key chain then the key has not been
 
123
                   * deleted yet.
 
124
                   *
 
125
                   * Now try to acquire the second lock without deadlocking.
 
126
                   * If we fail, we need to relinquish the first lock and the
 
127
                   * processor and then try to acquire them all again.
 
128
                   */
 
129
                  if (pthread_mutex_trylock(&(assoc->key->keyLock)) == EBUSY)
 
130
                    {
 
131
                      pthread_mutex_unlock(&(sp->threadLock));
 
132
                      Sleep(1); // Ugly but necessary to avoid priority effects.
 
133
                      /*
 
134
                       * Go around again.
 
135
                       * If pthread_key_delete has removed this assoc in the meantime,
 
136
                       * sp->nextAssoc will point to a new assoc.
 
137
                       */
 
138
                      continue;
 
139
                    }
 
140
                }
 
141
 
 
142
              /* We now hold both locks */
 
143
 
 
144
              sp->nextAssoc = assoc->nextKey;
 
145
 
 
146
              /*
 
147
               * Key still active; pthread_key_delete
 
148
               * will block on these same mutexes before
 
149
               * it can release actual key; therefore,
 
150
               * key is valid and we can call the destroy
 
151
               * routine;
 
152
               */
 
153
              k = assoc->key;
 
154
              destructor = k->destructor;
 
155
              value = TlsGetValue(k->key);
 
156
              TlsSetValue (k->key, NULL);
 
157
 
 
158
              // Every assoc->key exists and has a destructor
 
159
              if (value != NULL && iterations <= PTHREAD_DESTRUCTOR_ITERATIONS)
 
160
                {
 
161
                  /*
 
162
                   * Unlock both locks before the destructor runs.
 
163
                   * POSIX says pthread_key_delete can be run from destructors,
 
164
                   * and that probably includes with this key as target.
 
165
                   * pthread_setspecific can also be run from destructors and
 
166
                   * also needs to be able to access the assocs.
 
167
                   */
 
168
                  (void) pthread_mutex_unlock(&(sp->threadLock));
 
169
                  (void) pthread_mutex_unlock(&(k->keyLock));
 
170
 
 
171
                  assocsRemaining++;
 
172
 
 
173
#ifdef __cplusplus
 
174
 
 
175
                  try
 
176
                    {
 
177
                      /*
 
178
                       * Run the caller's cleanup routine.
 
179
                       */
 
180
                      destructor (value);
 
181
                    }
 
182
                  catch (...)
 
183
                    {
 
184
                      /*
 
185
                       * A system unexpected exception has occurred
 
186
                       * running the user's destructor.
 
187
                       * We get control back within this block in case
 
188
                       * the application has set up it's own terminate
 
189
                       * handler. Since we are leaving the thread we
 
190
                       * should not get any internal pthreads
 
191
                       * exceptions.
 
192
                       */
 
193
                      terminate ();
 
194
                    }
 
195
 
 
196
#else /* __cplusplus */
 
197
 
 
198
                  /*
 
199
                   * Run the caller's cleanup routine.
 
200
                   */
 
201
                  destructor (value);
 
202
 
 
203
#endif /* __cplusplus */
 
204
 
 
205
                }
 
206
              else
 
207
                {
 
208
                  /*
 
209
                   * Remove association from both the key and thread chains
 
210
                   * and reclaim it's memory resources.
 
211
                   */
 
212
                  ptw32_tkAssocDestroy (assoc);
 
213
                  (void) pthread_mutex_unlock(&(sp->threadLock));
 
214
                  (void) pthread_mutex_unlock(&(k->keyLock));
 
215
                }
 
216
            }
 
217
        }
 
218
      while (assocsRemaining);
 
219
    }
 
220
}                               /* ptw32_callUserDestroyRoutines */