]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/threadengines/threadengine_pthread.cpp
m_dnsbl updates
[user/henk/code/inspircd.git] / src / threadengines / threadengine_pthread.cpp
1 /*       +------------------------------------+
2  *       | Inspire Internet Relay Chat Daemon |
3  *       +------------------------------------+
4  *
5  *  InspIRCd: (C) 2002-2010 InspIRCd Development Team
6  * See: http://wiki.inspircd.org/Credits
7  *
8  * This program is free but copyrighted software; see
9  *          the file COPYING for details.
10  *
11  * ---------------------------------------------------
12  */
13
14 #include "inspircd.h"
15 #include "threadengines/threadengine_pthread.h"
16 #include <pthread.h>
17 #include <signal.h>
18 #include <fcntl.h>
19
20 ThreadEngine::ThreadEngine()
21 {
22 }
23
24 static void* entry_point(void* parameter)
25 {
26         /* Recommended by nenolod, signal safety on a per-thread basis */
27         sigset_t set;
28         sigemptyset(&set);
29         sigaddset(&set, SIGPIPE);
30         pthread_sigmask(SIG_BLOCK, &set, NULL);
31
32         Thread* pt = static_cast<Thread*>(parameter);
33         pt->Run();
34         return parameter;
35 }
36
37
38 void ThreadEngine::Start(Thread* thread)
39 {
40         ThreadData* data = new ThreadData;
41         thread->state = data;
42
43         if (pthread_create(&data->pthread_id, NULL, entry_point, thread) != 0)
44         {
45                 thread->state = NULL;
46                 delete data;
47                 throw CoreException("Unable to create new thread: " + std::string(strerror(errno)));
48         }
49 }
50
51 ThreadEngine::~ThreadEngine()
52 {
53 }
54
55 void ThreadData::FreeThread(Thread* thread)
56 {
57         thread->SetExitFlag();
58         pthread_join(pthread_id, NULL);
59 }
60
61 #ifdef HAS_EVENTFD
62 #include <sys/eventfd.h>
63
64 class ThreadSignalSocket : public BufferedSocket
65 {
66         SocketThread* parent;
67  public:
68         ThreadSignalSocket(SocketThread* p, int newfd) : BufferedSocket(newfd), parent(p) {}
69
70         ~ThreadSignalSocket()
71         {
72         }
73
74         void Notify()
75         {
76                 eventfd_write(fd, 1);
77         }
78
79         void OnDataReady()
80         {
81                 recvq.clear();
82                 parent->OnNotify();
83         }
84
85         void OnError(BufferedSocketError)
86         {
87                 ServerInstance->GlobalCulls.AddItem(this);
88         }
89 };
90
91 SocketThread::SocketThread()
92 {
93         int fd = eventfd(0, O_NONBLOCK);
94         if (fd < 0)
95                 throw new CoreException("Could not create pipe " + std::string(strerror(errno)));
96         signal.sock = new ThreadSignalSocket(this, fd);
97 }
98 #else
99
100 class ThreadSignalSocket : public BufferedSocket
101 {
102         SocketThread* parent;
103         int send_fd;
104  public:
105         ThreadSignalSocket(SocketThread* p, int recvfd, int sendfd) :
106                 BufferedSocket(recvfd), parent(p), send_fd(sendfd)  {}
107
108         ~ThreadSignalSocket()
109         {
110                 close(send_fd);
111         }
112
113         void Notify()
114         {
115                 char dummy = '*';
116                 write(send_fd, &dummy, 1);
117         }
118
119         void OnDataReady()
120         {
121                 recvq.clear();
122                 parent->OnNotify();
123         }
124
125         void OnError(BufferedSocketError)
126         {
127                 ServerInstance->GlobalCulls.AddItem(this);
128         }
129 };
130
131 SocketThread::SocketThread()
132 {
133         int fds[2];
134         if (pipe(fds))
135                 throw new CoreException("Could not create pipe " + std::string(strerror(errno)));
136         signal.sock = new ThreadSignalSocket(this, fds[0], fds[1]);
137 }
138 #endif
139
140 void SocketThread::NotifyParent()
141 {
142         signal.sock->Notify();
143 }
144
145 SocketThread::~SocketThread()
146 {
147 }