testprocmutex.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. /* Licensed to the Apache Software Foundation (ASF) under one or more
  2. * contributor license agreements. See the NOTICE file distributed with
  3. * this work for additional information regarding copyright ownership.
  4. * The ASF licenses this file to You under the Apache License, Version 2.0
  5. * (the "License"); you may not use this file except in compliance with
  6. * the License. You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include "fspr_shm.h"
  17. #include "fspr_thread_proc.h"
  18. #include "fspr_file_io.h"
  19. #include "fspr_proc_mutex.h"
  20. #include "fspr_errno.h"
  21. #include "fspr_general.h"
  22. #include "fspr_getopt.h"
  23. #include "errno.h"
  24. #include <stdio.h>
  25. #include <stdlib.h>
  26. #include "testutil.h"
  27. #if APR_HAS_FORK
  28. #define MAX_ITER 200
  29. #define CHILDREN 6
  30. #define MAX_COUNTER (MAX_ITER * CHILDREN)
  31. static fspr_proc_mutex_t *proc_lock;
  32. static volatile int *x;
  33. /* a slower more racy way to implement (*x)++ */
  34. static int increment(int n)
  35. {
  36. fspr_sleep(1);
  37. return n+1;
  38. }
  39. static void make_child(abts_case *tc, fspr_proc_t **proc, fspr_pool_t *p)
  40. {
  41. fspr_status_t rv;
  42. *proc = fspr_pcalloc(p, sizeof(**proc));
  43. /* slight delay to allow things to settle */
  44. fspr_sleep (1);
  45. rv = fspr_proc_fork(*proc, p);
  46. if (rv == APR_INCHILD) {
  47. int i = 0;
  48. /* The parent process has setup all processes to call fspr_terminate
  49. * at exit. But, that means that all processes must also call
  50. * fspr_initialize at startup. You cannot have an unequal number
  51. * of fspr_terminate and fspr_initialize calls. If you do, bad things
  52. * will happen. In this case, the bad thing is that if the mutex
  53. * is a semaphore, it will be destroyed before all of the processes
  54. * die. That means that the test will most likely fail.
  55. */
  56. fspr_initialize();
  57. if (fspr_proc_mutex_child_init(&proc_lock, NULL, p))
  58. exit(1);
  59. do {
  60. if (fspr_proc_mutex_lock(proc_lock))
  61. exit(1);
  62. i++;
  63. *x = increment(*x);
  64. if (fspr_proc_mutex_unlock(proc_lock))
  65. exit(1);
  66. } while (i < MAX_ITER);
  67. exit(0);
  68. }
  69. ABTS_ASSERT(tc, "fork failed", rv == APR_INPARENT);
  70. }
  71. /* Wait for a child process and check it terminated with success. */
  72. static void await_child(abts_case *tc, fspr_proc_t *proc)
  73. {
  74. int code;
  75. fspr_exit_why_e why;
  76. fspr_status_t rv;
  77. rv = fspr_proc_wait(proc, &code, &why, APR_WAIT);
  78. ABTS_ASSERT(tc, "child did not terminate with success",
  79. rv == APR_CHILD_DONE && why == APR_PROC_EXIT && code == 0);
  80. }
  81. static void test_exclusive(abts_case *tc, const char *lockname,
  82. fspr_lockmech_e mech)
  83. {
  84. fspr_proc_t *child[CHILDREN];
  85. fspr_status_t rv;
  86. int n;
  87. rv = fspr_proc_mutex_create(&proc_lock, lockname, mech, p);
  88. APR_ASSERT_SUCCESS(tc, "create the mutex", rv);
  89. if (rv != APR_SUCCESS)
  90. return;
  91. for (n = 0; n < CHILDREN; n++)
  92. make_child(tc, &child[n], p);
  93. for (n = 0; n < CHILDREN; n++)
  94. await_child(tc, child[n]);
  95. ABTS_ASSERT(tc, "Locks don't appear to work", *x == MAX_COUNTER);
  96. }
  97. #endif
  98. static void proc_mutex(abts_case *tc, void *data)
  99. {
  100. #if APR_HAS_FORK
  101. fspr_status_t rv;
  102. const char *shmname = "tpm.shm";
  103. fspr_shm_t *shm;
  104. fspr_lockmech_e *mech = data;
  105. /* Use anonymous shm if available. */
  106. rv = fspr_shm_create(&shm, sizeof(int), NULL, p);
  107. if (rv == APR_ENOTIMPL) {
  108. fspr_file_remove(shmname, p);
  109. rv = fspr_shm_create(&shm, sizeof(int), shmname, p);
  110. }
  111. APR_ASSERT_SUCCESS(tc, "create shm segment", rv);
  112. if (rv != APR_SUCCESS)
  113. return;
  114. x = fspr_shm_baseaddr_get(shm);
  115. test_exclusive(tc, NULL, *mech);
  116. rv = fspr_shm_destroy(shm);
  117. APR_ASSERT_SUCCESS(tc, "Error destroying shared memory block", rv);
  118. #else
  119. ABTS_NOT_IMPL(tc, "APR lacks fork() support");
  120. #endif
  121. }
  122. abts_suite *testprocmutex(abts_suite *suite)
  123. {
  124. fspr_lockmech_e mech = APR_LOCK_DEFAULT;
  125. suite = ADD_SUITE(suite)
  126. abts_run_test(suite, proc_mutex, &mech);
  127. #if APR_HAS_POSIXSEM_SERIALIZE
  128. mech = APR_LOCK_POSIXSEM;
  129. abts_run_test(suite, proc_mutex, &mech);
  130. #endif
  131. #if APR_HAS_SYSVSEM_SERIALIZE
  132. mech = APR_LOCK_SYSVSEM;
  133. abts_run_test(suite, proc_mutex, &mech);
  134. #endif
  135. #if APR_HAS_PROC_PTHREAD_SERIALIZE
  136. mech = APR_LOCK_PROC_PTHREAD;
  137. abts_run_test(suite, proc_mutex, &mech);
  138. #endif
  139. #if APR_HAS_FCNTL_SERIALIZE
  140. mech = APR_LOCK_FCNTL;
  141. abts_run_test(suite, proc_mutex, &mech);
  142. #endif
  143. #if APR_HAS_FLOCK_SERIALIZE
  144. mech = APR_LOCK_FLOCK;
  145. abts_run_test(suite, proc_mutex, &mech);
  146. #endif
  147. return suite;
  148. }