selectinterrupter.cpp 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. /**
  2. * Copyright (c) 2020-2021 Paul-Louis Ageneau
  3. *
  4. * This library is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU Lesser General Public
  6. * License as published by the Free Software Foundation; either
  7. * version 2.1 of the License, or (at your option) any later version.
  8. *
  9. * This library is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * Lesser General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU Lesser General Public
  15. * License along with this library; if not, write to the Free Software
  16. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  17. */
  18. #include "selectinterrupter.hpp"
  19. #include "internals.hpp"
  20. #if RTC_ENABLE_WEBSOCKET
  21. #ifndef _WIN32
  22. #include <fcntl.h>
  23. #include <unistd.h>
  24. #endif
  25. namespace rtc::impl {
  26. SelectInterrupter::SelectInterrupter() {
  27. #ifndef _WIN32
  28. int pipefd[2];
  29. if (::pipe(pipefd) != 0)
  30. throw std::runtime_error("Failed to create pipe");
  31. ::fcntl(pipefd[0], F_SETFL, O_NONBLOCK);
  32. ::fcntl(pipefd[1], F_SETFL, O_NONBLOCK);
  33. mPipeOut = pipefd[1]; // read
  34. mPipeIn = pipefd[0]; // write
  35. #endif
  36. }
  37. SelectInterrupter::~SelectInterrupter() {
  38. std::lock_guard lock(mMutex);
  39. #ifdef _WIN32
  40. if (mDummySock != INVALID_SOCKET)
  41. ::closesocket(mDummySock);
  42. #else
  43. ::close(mPipeIn);
  44. ::close(mPipeOut);
  45. #endif
  46. }
  47. int SelectInterrupter::prepare(fd_set &readfds) {
  48. std::lock_guard lock(mMutex);
  49. #ifdef _WIN32
  50. if (mDummySock == INVALID_SOCKET)
  51. mDummySock = ::socket(AF_INET, SOCK_DGRAM, 0);
  52. FD_SET(mDummySock, &readfds);
  53. return SOCKET_TO_INT(mDummySock) + 1;
  54. #else
  55. char dummy;
  56. if (::read(mPipeIn, &dummy, 1) < 0 && errno != EAGAIN && errno != EWOULDBLOCK) {
  57. PLOG_WARNING << "Reading from interrupter pipe failed, errno=" << errno;
  58. }
  59. FD_SET(mPipeIn, &readfds);
  60. return mPipeIn + 1;
  61. #endif
  62. }
  63. void SelectInterrupter::interrupt() {
  64. std::lock_guard lock(mMutex);
  65. #ifdef _WIN32
  66. if (mDummySock != INVALID_SOCKET) {
  67. ::closesocket(mDummySock);
  68. mDummySock = INVALID_SOCKET;
  69. }
  70. #else
  71. char dummy = 0;
  72. if (::write(mPipeOut, &dummy, 1) < 0 && errno != EAGAIN && errno != EWOULDBLOCK) {
  73. PLOG_WARNING << "Writing to interrupter pipe failed, errno=" << errno;
  74. }
  75. #endif
  76. }
  77. } // namespace rtc::impl
  78. #endif