abyss_thread_fork.c
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include <sys/types.h>
00036 #include <stdlib.h>
00037 #include <unistd.h>
00038 #include <string.h>
00039 #include <errno.h>
00040 #include <sys/wait.h>
00041 #include <signal.h>
00042
00043 #include <xmlrpc-c/config.h>
00044 #include "abyss_xmlrpc_int.h"
00045 #include <xmlrpc-c/abyss.h>
00046
00047 #include "abyss_mallocvar.h"
00048 #include "abyss_thread.h"
00049
00050
00051 static void
00052 blockSignalClass(int const signalClass,
00053 sigset_t * const oldBlockedSetP) {
00054
00055 sigset_t newBlockedSet;
00056
00057 sigemptyset(&newBlockedSet);
00058 sigaddset(&newBlockedSet, signalClass);
00059
00060 sigprocmask(SIG_BLOCK, &newBlockedSet, oldBlockedSetP);
00061 }
00062
00063
00064
00065 struct abyss_thread {
00066 struct abyss_thread * nextInPoolP;
00067 TThreadDoneFn * threadDone;
00068 void * userHandle;
00069 pid_t pid;
00070 abyss_bool useSigchld;
00071
00072
00073
00074
00075
00076 };
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090 static struct {
00091 struct abyss_thread * firstP;
00092 } ThreadPool;
00093
00094
00095
00096 void
00097 ThreadPoolInit(void) {
00098
00099 ThreadPool.firstP = NULL;
00100 }
00101
00102
00103
00104 static struct abyss_thread *
00105 findThread(pid_t const pid) {
00106
00107 struct abyss_thread * p;
00108
00109 for (p = ThreadPool.firstP; p && p->pid != pid; p = p->nextInPoolP);
00110
00111 return p;
00112 }
00113
00114
00115
00116 static void
00117 addToPool(struct abyss_thread * const threadP) {
00118
00119 if (ThreadPool.firstP == NULL)
00120 ThreadPool.firstP = threadP;
00121 else {
00122 struct abyss_thread * p;
00123
00124 for (p = ThreadPool.firstP; p->nextInPoolP; p = p->nextInPoolP);
00125
00126
00127
00128 p->nextInPoolP = threadP;
00129 }
00130 }
00131
00132
00133
00134 static void
00135 removeFromPool(struct abyss_thread * const threadP) {
00136
00137 if (threadP == ThreadPool.firstP)
00138 ThreadPool.firstP = threadP->nextInPoolP;
00139 else {
00140 struct abyss_thread * p;
00141
00142 for (p = ThreadPool.firstP;
00143 p && p->nextInPoolP != threadP;
00144 p = p->nextInPoolP);
00145
00146 if (p)
00147
00148 p->nextInPoolP = threadP->nextInPoolP;
00149 }
00150 }
00151
00152
00153
00154 void
00155 ThreadHandleSigchld(pid_t const pid) {
00156
00157
00158
00159
00160 struct abyss_thread * const threadP = findThread(pid);
00161
00162 if (threadP) {
00163 if (threadP->threadDone)
00164 threadP->threadDone(threadP->userHandle);
00165 threadP->pid = 0;
00166 }
00167
00168 }
00169
00170
00171
00172 void
00173 ThreadUpdateStatus(TThread * const threadP) {
00174
00175 if (!threadP->useSigchld) {
00176 if (threadP->pid) {
00177 if (kill(threadP->pid, 0) != 0) {
00178 if (threadP->threadDone)
00179 threadP->threadDone(threadP->userHandle);
00180 threadP->pid = 0;
00181 }
00182 }
00183 }
00184 }
00185
00186
00187
00188 void
00189 ThreadCreate(TThread ** const threadPP,
00190 void * const userHandle,
00191 TThreadProc * const func,
00192 TThreadDoneFn * const threadDone,
00193 abyss_bool const useSigchld,
00194 const char ** const errorP) {
00195
00196 TThread * threadP;
00197
00198 MALLOCVAR(threadP);
00199 if (threadP == NULL)
00200 xmlrpc_asprintf(errorP,
00201 "Can't allocate memory for thread descriptor.");
00202 else {
00203 sigset_t oldBlockedSet;
00204 pid_t rc;
00205
00206 threadP->nextInPoolP = NULL;
00207 threadP->threadDone = threadDone;
00208 threadP->userHandle = userHandle;
00209 threadP->useSigchld = useSigchld;
00210 threadP->pid = 0;
00211
00212
00213
00214
00215
00216 blockSignalClass(SIGCHLD, &oldBlockedSet);
00217
00218 rc = fork();
00219
00220 if (rc < 0)
00221 xmlrpc_asprintf(errorP, "fork() failed, errno=%d (%s)",
00222 errno, strerror(errno));
00223 else if (rc == 0) {
00224
00225 (*func)(userHandle);
00226 exit(0);
00227 } else {
00228
00229 threadP->pid = rc;
00230
00231 addToPool(threadP);
00232
00233 sigprocmask(SIG_SETMASK, &oldBlockedSet, NULL);
00234
00235 *errorP = NULL;
00236 *threadPP = threadP;
00237 }
00238 if (*errorP) {
00239 removeFromPool(threadP);
00240 free(threadP);
00241 }
00242 }
00243 }
00244
00245
00246
00247 abyss_bool
00248 ThreadRun(TThread * const threadP ATTR_UNUSED) {
00249 return TRUE;
00250 }
00251
00252
00253
00254 abyss_bool
00255 ThreadStop(TThread * const threadP ATTR_UNUSED) {
00256 return TRUE;
00257 }
00258
00259
00260
00261 abyss_bool
00262 ThreadKill(TThread * const threadP ATTR_UNUSED) {
00263 return TRUE;
00264 }
00265
00266
00267
00268 void
00269 ThreadWaitAndRelease(TThread * const threadP) {
00270
00271 if (threadP->pid) {
00272 int exitStatus;
00273
00274 waitpid(threadP->pid, &exitStatus, 0);
00275
00276 threadP->threadDone(threadP->userHandle);
00277
00278 threadP->pid = 0;
00279 }
00280 ThreadRelease(threadP);
00281 }
00282
00283
00284
00285 void
00286 ThreadExit(int const retValue) {
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296 exit(retValue);
00297 }
00298
00299
00300
00301 void
00302 ThreadRelease(TThread * const threadP) {
00303
00304 removeFromPool(threadP);
00305 free(threadP);
00306 }
00307
00308
00309
00310 abyss_bool
00311 ThreadForks(void) {
00312
00313 return TRUE;
00314 }
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326 abyss_bool
00327 MutexCreate(TMutex * const mutexP ATTR_UNUSED) {
00328 return TRUE;
00329 }
00330
00331
00332
00333 abyss_bool
00334 MutexLock(TMutex * const mutexP ATTR_UNUSED) {
00335 return TRUE;
00336 }
00337
00338
00339
00340 abyss_bool
00341 MutexUnlock(TMutex * const mutexP ATTR_UNUSED) {
00342 return TRUE;
00343 }
00344
00345
00346
00347 abyss_bool
00348 MutexTryLock(TMutex * const mutexP ATTR_UNUSED) {
00349 return TRUE;
00350 }
00351
00352
00353
00354 void
00355 MutexFree(TMutex * const mutexP ATTR_UNUSED) {
00356
00357 }