xref: /PHP-5.5/sapi/fpm/fpm/events/port.c (revision 73c1be26)
1 /*
2    +----------------------------------------------------------------------+
3    | PHP Version 5                                                        |
4    +----------------------------------------------------------------------+
5    | Copyright (c) 1997-2015 The PHP Group                                |
6    +----------------------------------------------------------------------+
7    | This source file is subject to version 3.01 of the PHP license,      |
8    | that is bundled with this package in the file LICENSE, and is        |
9    | available through the world-wide-web at the following url:           |
10    | http://www.php.net/license/3_01.txt                                  |
11    | If you did not receive a copy of the PHP license and are unable to   |
12    | obtain it through the world-wide-web, please send a note to          |
13    | license@php.net so we can mail you a copy immediately.               |
14    +----------------------------------------------------------------------+
15    | Authors: Jerome Loyet <jerome@loyet.net>                             |
16    +----------------------------------------------------------------------+
17 */
18 
19 /* $Id$ */
20 
21 #include "../fpm_config.h"
22 #include "../fpm_events.h"
23 #include "../fpm.h"
24 #include "../zlog.h"
25 
26 #if HAVE_PORT
27 
28 #include <port.h>
29 #include <poll.h>
30 #include <errno.h>
31 
32 static int fpm_event_port_init(int max);
33 static int fpm_event_port_clean();
34 static int fpm_event_port_wait(struct fpm_event_queue_s *queue, unsigned long int timeout);
35 static int fpm_event_port_add(struct fpm_event_s *ev);
36 static int fpm_event_port_remove(struct fpm_event_s *ev);
37 
38 static struct fpm_event_module_s port_module = {
39 	.name = "port",
40 	.support_edge_trigger = 0,
41 	.init = fpm_event_port_init,
42 	.clean = fpm_event_port_clean,
43 	.wait = fpm_event_port_wait,
44 	.add = fpm_event_port_add,
45 	.remove = fpm_event_port_remove,
46 };
47 
48 port_event_t *events = NULL;
49 int nevents = 0;
50 static int pfd = -1;
51 
52 #endif /* HAVE_PORT */
53 
fpm_event_port_module()54 struct fpm_event_module_s *fpm_event_port_module() /* {{{ */
55 {
56 #if HAVE_PORT
57 	return &port_module;
58 #else
59 	return NULL;
60 #endif /* HAVE_PORT */
61 }
62 /* }}} */
63 
64 #if HAVE_PORT
65 
66 /*
67  * Init the module
68  */
fpm_event_port_init(int max)69 static int fpm_event_port_init(int max) /* {{{ */
70 {
71 	/* open port */
72 	pfd = port_create();
73 	if (pfd < 0) {
74 		zlog(ZLOG_ERROR, "port: unable to initialize port_create()");
75 		return -1;
76 	}
77 
78 	if (max < 1) {
79 		return 0;
80 	}
81 
82 	/* alloc and clear active_pollfds */
83 	events = malloc(sizeof(port_event_t) * max);
84 	if (!events) {
85 		zlog(ZLOG_ERROR, "port: Unable to allocate %d events", max);
86 		return -1;
87 	}
88 
89 	nevents = max;
90 	return 0;
91 }
92 /* }}} */
93 
94 /*
95  * Clean the module
96  */
fpm_event_port_clean()97 static int fpm_event_port_clean() /* {{{ */
98 {
99 	if (pfd > -1) {
100 		close(pfd);
101 		pfd = -1;
102 	}
103 
104 	if (events) {
105 		free(events);
106 		events = NULL;
107 	}
108 
109 	nevents = 0;
110 	return 0;
111 }
112 /* }}} */
113 
114 /*
115  * wait for events or timeout
116  */
fpm_event_port_wait(struct fpm_event_queue_s * queue,unsigned long int timeout)117 static int fpm_event_port_wait(struct fpm_event_queue_s *queue, unsigned long int timeout) /* {{{ */
118 {
119 	int ret, i, nget;
120 	timespec_t t;
121 
122 	/* convert timeout into timespec_t */
123 	t.tv_sec = (int)(timeout / 1000);
124 	t.tv_nsec = (timeout % 1000) * 1000 * 1000;
125 
126 	/* wait for inconming event or timeout. We want at least one event or timeout */
127 	nget = 1;
128 	ret = port_getn(pfd, events, nevents, &nget, &t);
129 	if (ret < 0) {
130 
131 		/* trigger error unless signal interrupt or timeout */
132 		if (errno != EINTR && errno != ETIME) {
133 			zlog(ZLOG_WARNING, "poll() returns %d", errno);
134 			return -1;
135 		}
136 	}
137 
138 	for (i = 0; i < nget; i++) {
139 
140 		/* do we have a ptr to the event ? */
141 		if (!events[i].portev_user) {
142 			continue;
143 		}
144 
145 		/* fire the event */
146 		fpm_event_fire((struct fpm_event_s *)events[i].portev_user);
147 
148 		/* sanity check */
149 		if (fpm_globals.parent_pid != getpid()) {
150 			return -2;
151 		}
152 	}
153 	return nget;
154 }
155 /* }}} */
156 
157 /*
158  * Add a FD to the fd set
159  */
fpm_event_port_add(struct fpm_event_s * ev)160 static int fpm_event_port_add(struct fpm_event_s *ev) /* {{{ */
161 {
162 	/* add the event to port */
163 	if (port_associate(pfd, PORT_SOURCE_FD, ev->fd, POLLIN, (void *)ev) < 0) {
164 		zlog(ZLOG_ERROR, "port: unable to add the event");
165 		return -1;
166 	}
167 	return 0;
168 }
169 /* }}} */
170 
171 /*
172  * Remove a FD from the fd set
173  */
fpm_event_port_remove(struct fpm_event_s * ev)174 static int fpm_event_port_remove(struct fpm_event_s *ev) /* {{{ */
175 {
176 	/* remove the event from port */
177 	if (port_dissociate(pfd, PORT_SOURCE_FD, ev->fd) < 0) {
178 		zlog(ZLOG_ERROR, "port: unable to add the event");
179 		return -1;
180 	}
181 	return 0;
182 }
183 /* }}} */
184 
185 #endif /* HAVE_PORT */
186