lib1541.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. /***************************************************************************
  2. * _ _ ____ _
  3. * Project ___| | | | _ \| |
  4. * / __| | | | |_) | |
  5. * | (__| |_| | _ <| |___
  6. * \___|\___/|_| \_\_____|
  7. *
  8. * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
  9. *
  10. * This software is licensed as described in the file COPYING, which
  11. * you should have received as part of this distribution. The terms
  12. * are also available at https://curl.se/docs/copyright.html.
  13. *
  14. * You may opt to use, copy, modify, merge, publish, distribute and/or sell
  15. * copies of the Software, and permit persons to whom the Software is
  16. * furnished to do so, under the terms of the COPYING file.
  17. *
  18. * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
  19. * KIND, either express or implied.
  20. *
  21. * SPDX-License-Identifier: curl
  22. *
  23. ***************************************************************************/
  24. /*
  25. * KNOW_BUGS "A shared connection cache is not thread-safe"
  26. *
  27. * This source code was used to verify shared connection cache but since this
  28. * is a known issue the test is no longer built or run. This code is here to
  29. * allow for testing once someone gets to work on fixing this.
  30. */
  31. #include "test.h"
  32. #include "testutil.h"
  33. #include "warnless.h"
  34. #include "memdebug.h"
  35. #ifdef HAVE_PTHREAD_H
  36. #include <pthread.h>
  37. #include <time.h>
  38. /* number of threads to fire up in parallel */
  39. #define NUM_THREADS 67
  40. /* for how many seconds each thread will loop */
  41. #define RUN_FOR_SECONDS 7
  42. static pthread_mutex_t connlock;
  43. static size_t write_db(void *ptr, size_t size, size_t nmemb, void *data)
  44. {
  45. /* not interested in the downloaded bytes, return the size */
  46. (void)ptr; /* unused */
  47. (void)data; /* unused */
  48. return (size_t)(size * nmemb);
  49. }
  50. static void lock_cb(CURL *handle, curl_lock_data data,
  51. curl_lock_access access, void *userptr)
  52. {
  53. (void)access; /* unused */
  54. (void)userptr; /* unused */
  55. (void)handle; /* unused */
  56. (void)data; /* unused */
  57. pthread_mutex_lock(&connlock);
  58. }
  59. static void unlock_cb(CURL *handle, curl_lock_data data,
  60. void *userptr)
  61. {
  62. (void)userptr; /* unused */
  63. (void)handle; /* unused */
  64. (void)data; /* unused */
  65. pthread_mutex_unlock(&connlock);
  66. }
  67. static void init_locks(void)
  68. {
  69. pthread_mutex_init(&connlock, NULL);
  70. }
  71. static void kill_locks(void)
  72. {
  73. pthread_mutex_destroy(&connlock);
  74. }
  75. struct initurl {
  76. const char *url;
  77. CURLSH *share;
  78. int threadno;
  79. };
  80. static void *run_thread(void *ptr)
  81. {
  82. struct initurl *u = (struct initurl *)ptr;
  83. int i;
  84. time_t end = time(NULL) + RUN_FOR_SECONDS;
  85. for(i = 0; time(NULL) < end; i++) {
  86. CURL *curl = curl_easy_init();
  87. curl_easy_setopt(curl, CURLOPT_URL, u->url);
  88. curl_easy_setopt(curl, CURLOPT_VERBOSE, 0L);
  89. curl_easy_setopt(curl, CURLOPT_SHARE, u->share);
  90. curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_db);
  91. curl_easy_perform(curl); /* ignores error */
  92. curl_easy_cleanup(curl);
  93. fprintf(stderr, "Thread %d transfer %d\n", u->threadno, i);
  94. }
  95. return NULL;
  96. }
  97. int test(char *URL)
  98. {
  99. pthread_t tid[NUM_THREADS];
  100. int i;
  101. CURLSH *share;
  102. struct initurl url[NUM_THREADS];
  103. /* Must initialize libcurl before any threads are started */
  104. curl_global_init(CURL_GLOBAL_ALL);
  105. share = curl_share_init();
  106. curl_share_setopt(share, CURLSHOPT_LOCKFUNC, lock_cb);
  107. curl_share_setopt(share, CURLSHOPT_UNLOCKFUNC, unlock_cb);
  108. curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_CONNECT);
  109. init_locks();
  110. for(i = 0; i< NUM_THREADS; i++) {
  111. int error;
  112. url[i].url = URL;
  113. url[i].share = share;
  114. url[i].threadno = i;
  115. error = pthread_create(&tid[i], NULL, run_thread, &url[i]);
  116. if(0 != error)
  117. fprintf(stderr, "Couldn't run thread number %d, errno %d\n", i, error);
  118. else
  119. fprintf(stderr, "Thread %d, gets %s\n", i, URL);
  120. }
  121. /* now wait for all threads to terminate */
  122. for(i = 0; i< NUM_THREADS; i++) {
  123. pthread_join(tid[i], NULL);
  124. fprintf(stderr, "Thread %d terminated\n", i);
  125. }
  126. kill_locks();
  127. curl_share_cleanup(share);
  128. curl_global_cleanup();
  129. return 0;
  130. }
  131. #else /* without pthread, this test doesn't work */
  132. int test(char *URL)
  133. {
  134. (void)URL;
  135. return 0;
  136. }
  137. #endif