Back to index

lightning-sunbird  0.9+nobinonly
intrupt.c
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is the Netscape Portable Runtime (NSPR).
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998-2000
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 /*
00039  * File:        intrupt.c
00040  * Purpose:     testing thread interrupts
00041  */
00042 
00043 #include "plgetopt.h"
00044 #include "prcvar.h"
00045 #include "prerror.h"
00046 #include "prinit.h"
00047 #include "prinrval.h"
00048 #include "prio.h"
00049 #include "prlock.h"
00050 #include "prlog.h"
00051 #include "prthread.h"
00052 #include "prtypes.h"
00053 #include "prnetdb.h"
00054 
00055 #include <stdio.h>
00056 #include <string.h>
00057 
00058 #ifdef XP_MAC
00059 #include "prlog.h"
00060 #define printf PR_LogPrint
00061 extern void SetupMacPrintfLog(char *logFile);
00062 #endif
00063 
00064 #define DEFAULT_TCP_PORT 12500
00065 
00066 static PRLock *ml = NULL;
00067 static PRCondVar *cv = NULL;
00068 
00069 static PRBool passed = PR_TRUE;
00070 static PRBool debug_mode = PR_FALSE;
00071 static PRThreadScope thread_scope = PR_LOCAL_THREAD;
00072 
00073 static void PR_CALLBACK AbortCV(void *arg)
00074 {
00075     PRStatus rv;
00076     PRThread *me = PR_CurrentThread();
00077 
00078     /* some other thread (main) is doing the interrupt */
00079     PR_Lock(ml);
00080     rv = PR_WaitCondVar(cv, PR_INTERVAL_NO_TIMEOUT);
00081     if (debug_mode) printf( "Expected interrupt on wait CV and ");
00082     if (PR_FAILURE == rv)
00083     {
00084         if (PR_PENDING_INTERRUPT_ERROR == PR_GetError())
00085         {
00086             if (debug_mode) printf("got it\n");
00087         }
00088         else
00089         {
00090             if (debug_mode) printf("got random error\n");
00091             passed = PR_FALSE;
00092         }
00093     }
00094     else
00095     {
00096         if (debug_mode) printf("got a successful completion\n");
00097         passed = PR_FALSE;
00098     }
00099 
00100     rv = PR_WaitCondVar(cv, 10);
00101     if (debug_mode)
00102     {
00103         printf(
00104             "Expected success on wait CV and %s\n",
00105             (PR_SUCCESS == rv) ? "got it" : "failed");
00106     }
00107     passed = ((PR_TRUE == passed) && (PR_SUCCESS == rv)) ? PR_TRUE : PR_FALSE;
00108 
00109     /* interrupt myself, then clear */
00110     PR_Interrupt(me);
00111     PR_ClearInterrupt();
00112     rv = PR_WaitCondVar(cv, 10);
00113     if (debug_mode)
00114     {
00115         printf("Expected success on wait CV and ");
00116         if (PR_FAILURE == rv)
00117         {
00118             printf(
00119                 "%s\n", (PR_PENDING_INTERRUPT_ERROR == PR_GetError()) ?
00120                 "got interrupted" : "a random failure");
00121         }
00122         printf("got it\n");
00123     }
00124     passed = ((PR_TRUE == passed) && (PR_SUCCESS == rv)) ? PR_TRUE : PR_FALSE;
00125 
00126     /* set, then wait - interrupt - then wait again */
00127     PR_Interrupt(me);
00128     rv = PR_WaitCondVar(cv, 10);
00129     if (debug_mode) printf( "Expected interrupt on wait CV and ");
00130     if (PR_FAILURE == rv)
00131     {
00132         if (PR_PENDING_INTERRUPT_ERROR == PR_GetError())
00133         {
00134             if (debug_mode) printf("got it\n");
00135         }
00136         else
00137         {
00138             if (debug_mode) printf("failed\n");
00139             passed = PR_FALSE;
00140         }
00141     }
00142     else
00143     {
00144         if (debug_mode) printf("got a successful completion\n");
00145         passed = PR_FALSE;
00146     }
00147 
00148     rv = PR_WaitCondVar(cv, 10);
00149     if (debug_mode)
00150     {
00151         printf(
00152             "Expected success on wait CV and %s\n",
00153             (PR_SUCCESS == rv) ? "got it" : "failed");
00154     }
00155     passed = ((PR_TRUE == passed) && (PR_SUCCESS == rv)) ? PR_TRUE : PR_FALSE;
00156 
00157     PR_Unlock(ml);
00158 
00159 }  /* AbortCV */
00160 
00161 static void PR_CALLBACK AbortIO(void *arg)
00162 {
00163     PRStatus rv;
00164     PR_Sleep(PR_SecondsToInterval(2));
00165     rv = PR_Interrupt((PRThread*)arg);
00166     PR_ASSERT(PR_SUCCESS == rv);
00167 }  /* AbortIO */
00168 
00169 static void PR_CALLBACK AbortJoin(void *arg)
00170 {
00171 }  /* AbortJoin */
00172 
00173 static void setup_listen_socket(PRFileDesc **listner, PRNetAddr *netaddr)
00174 {
00175     PRStatus rv;
00176     PRInt16 port = DEFAULT_TCP_PORT;
00177 
00178     *listner = PR_NewTCPSocket();
00179     PR_ASSERT(*listner != NULL);
00180     memset(netaddr, 0, sizeof(*netaddr));
00181     (*netaddr).inet.ip = PR_htonl(PR_INADDR_ANY);
00182     (*netaddr).inet.family = PR_AF_INET;
00183     do
00184     {
00185         (*netaddr).inet.port = PR_htons(port);
00186         rv = PR_Bind(*listner, netaddr);
00187         port += 1;
00188         PR_ASSERT(port < (DEFAULT_TCP_PORT + 10));
00189     } while (PR_FAILURE == rv);
00190 
00191     rv = PR_Listen(*listner, 5);
00192 
00193        if (PR_GetSockName(*listner, netaddr) < 0) {
00194               if (debug_mode) printf("intrupt: ERROR - PR_GetSockName failed\n");
00195               passed = PR_FALSE;
00196               return;
00197        }
00198 
00199 }
00200 
00201 static void PR_CALLBACK IntrBlock(void *arg)
00202 {
00203     PRStatus rv;
00204     PRNetAddr netaddr;
00205     PRFileDesc *listner;
00206 
00207     /* some other thread (main) is doing the interrupt */
00208        /* block the interrupt */
00209        PR_BlockInterrupt();
00210     PR_Lock(ml);
00211     rv = PR_WaitCondVar(cv, PR_SecondsToInterval(4));
00212        PR_Unlock(ml);
00213     if (debug_mode)
00214     {
00215         printf("Expected success on wait CV and ");
00216         if (PR_FAILURE == rv)
00217         {
00218             printf(
00219                 "%s\n", (PR_PENDING_INTERRUPT_ERROR == PR_GetError()) ?
00220                 "got interrupted" : "got a random failure");
00221         } else
00222               printf("got it\n");
00223     }
00224     passed = ((PR_TRUE == passed) && (PR_SUCCESS == rv)) ? PR_TRUE : PR_FALSE;
00225 
00226        setup_listen_socket(&listner, &netaddr);
00227        PR_UnblockInterrupt();
00228     if (PR_Accept(listner, &netaddr, PR_INTERVAL_NO_TIMEOUT) == NULL)
00229     {
00230         PRInt32 error = PR_GetError();
00231         if (debug_mode) printf("Expected interrupt on PR_Accept() and ");
00232         if (PR_PENDING_INTERRUPT_ERROR == error)
00233         {
00234             if (debug_mode) printf("got it\n");
00235         }
00236         else
00237         {
00238             if (debug_mode) printf("failed\n");
00239             passed = PR_FALSE;
00240         }
00241     }
00242     else
00243     {
00244         if (debug_mode) printf("Failed to interrupt PR_Accept()\n");
00245         passed = PR_FALSE;
00246     }
00247 
00248     (void)PR_Close(listner); listner = NULL;
00249 }  /* TestIntrBlock */
00250 
00251 void PR_CALLBACK Intrupt(void *arg)
00252 {
00253     PRStatus rv;
00254     PRNetAddr netaddr;
00255     PRFileDesc *listner;
00256     PRThread *abortCV, *abortIO, *abortJoin, *intrBlock;
00257 
00258     ml = PR_NewLock();
00259     cv = PR_NewCondVar(ml);
00260 
00261 #ifdef XP_MAC
00262        SetupMacPrintfLog("intrupt.log");
00263        debug_mode = PR_TRUE;
00264 #endif
00265 
00266     /* Part I */
00267     if (debug_mode) printf("Part I\n");
00268     abortCV = PR_CreateThread(
00269         PR_USER_THREAD, AbortCV, 0, PR_PRIORITY_NORMAL,
00270         thread_scope, PR_JOINABLE_THREAD, 0);
00271 
00272     PR_Sleep(PR_SecondsToInterval(2));
00273     rv = PR_Interrupt(abortCV);
00274     PR_ASSERT(PR_SUCCESS == rv);
00275     rv = PR_JoinThread(abortCV);
00276     PR_ASSERT(PR_SUCCESS == rv);
00277 
00278     /* Part II */
00279     if (debug_mode) printf("Part II\n");
00280     abortJoin = PR_CreateThread(
00281         PR_USER_THREAD, AbortJoin, 0, PR_PRIORITY_NORMAL,
00282         thread_scope, PR_JOINABLE_THREAD, 0);
00283     PR_Sleep(PR_SecondsToInterval(2));
00284     if (debug_mode) printf("Expecting to interrupt an exited thread ");
00285     rv = PR_Interrupt(abortJoin);
00286     PR_ASSERT(PR_SUCCESS == rv);
00287     rv = PR_JoinThread(abortJoin);
00288     PR_ASSERT(PR_SUCCESS == rv);
00289     if (debug_mode) printf("and succeeded\n");
00290 
00291     /* Part III */
00292     if (debug_mode) printf("Part III\n");
00293        setup_listen_socket(&listner, &netaddr);
00294     abortIO = PR_CreateThread(
00295         PR_USER_THREAD, AbortIO, PR_CurrentThread(), PR_PRIORITY_NORMAL,
00296         thread_scope, PR_JOINABLE_THREAD, 0);
00297 
00298     if (PR_Accept(listner, &netaddr, PR_INTERVAL_NO_TIMEOUT) == NULL)
00299     {
00300         PRInt32 error = PR_GetError();
00301         if (debug_mode) printf("Expected interrupt on PR_Accept() and ");
00302         if (PR_PENDING_INTERRUPT_ERROR == error)
00303         {
00304             if (debug_mode) printf("got it\n");
00305         }
00306         else
00307         {
00308             if (debug_mode) printf("failed\n");
00309             passed = PR_FALSE;
00310         }
00311     }
00312     else
00313     {
00314         if (debug_mode) printf("Failed to interrupt PR_Accept()\n");
00315         passed = PR_FALSE;
00316     }
00317 
00318     (void)PR_Close(listner); listner = NULL;
00319 
00320     rv = PR_JoinThread(abortIO);
00321     PR_ASSERT(PR_SUCCESS == rv);
00322     /* Part VI */
00323     if (debug_mode) printf("Part VI\n");
00324     intrBlock = PR_CreateThread(
00325         PR_USER_THREAD, IntrBlock, 0, PR_PRIORITY_NORMAL,
00326         thread_scope, PR_JOINABLE_THREAD, 0);
00327 
00328     PR_Sleep(PR_SecondsToInterval(2));
00329     rv = PR_Interrupt(intrBlock);
00330     PR_ASSERT(PR_SUCCESS == rv);
00331     rv = PR_JoinThread(intrBlock);
00332     PR_ASSERT(PR_SUCCESS == rv);
00333 
00334     PR_DestroyCondVar(cv);
00335     PR_DestroyLock(ml);    
00336 }  /* Intrupt */
00337 
00338 PRIntn main(PRIntn argc, char **argv)
00339 {
00340     PRThread *intrupt;
00341        PLOptStatus os;
00342        PLOptState *opt = PL_CreateOptState(argc, argv, "dG");
00343        while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
00344     {
00345               if (PL_OPT_BAD == os) continue;
00346         switch (opt->option)
00347         {
00348         case 'd':  /* debug mode */
00349                      debug_mode = PR_TRUE;
00350             break;
00351         case 'G':  /* use global threads */
00352             thread_scope = PR_GLOBAL_THREAD;
00353             break;
00354         }
00355     }
00356        PL_DestroyOptState(opt);
00357     PR_STDIO_INIT();
00358     intrupt = PR_CreateThread(
00359         PR_USER_THREAD, Intrupt, NULL, PR_PRIORITY_NORMAL,
00360         thread_scope, PR_JOINABLE_THREAD, 0);
00361     if (intrupt == NULL) {
00362         fprintf(stderr, "cannot create thread\n");
00363         passed = PR_FALSE;
00364     } else {
00365         PRStatus rv;
00366         rv = PR_JoinThread(intrupt);
00367         PR_ASSERT(rv == PR_SUCCESS);
00368     }
00369     printf("%s\n", ((passed) ? "PASSED" : "FAILED"));
00370        return ((passed) ? 0 : 1);
00371 }  /* main */
00372 
00373 /* intrupt.c */