Skip to content

Commit 9198faa

Browse files
committed
Convert resource to object in Sysvmsg
Closes GH-5546
1 parent 75bac16 commit 9198faa

File tree

6 files changed

+105
-74
lines changed

6 files changed

+105
-74
lines changed

UPGRADING

+5
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,11 @@ PHP 8.0 UPGRADE NOTES
418418
explicit setlocale() call is now always required if you wish to change any
419419
locale component from the default.
420420

421+
- Sysvmsg:
422+
. msg_get_queue() will now return an SysvMessageQueue object rather than a resource.
423+
Return value checks using is_resource() should be replaced with checks
424+
for `false`.
425+
421426
- Sysvsem:
422427
. sem_get() will now return an SysvSemaphore object rather than a resource.
423428
Return value checks using is_resource() should be replaced with checks

ext/sysvmsg/sysvmsg.c

+68-38
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "sysvmsg_arginfo.h"
2626
#include "ext/standard/php_var.h"
2727
#include "zend_smart_str.h"
28+
#include "Zend/zend_interfaces.h"
2829

2930
#include <sys/types.h>
3031
#include <sys/ipc.h>
@@ -36,6 +37,7 @@ PHP_MINFO_FUNCTION(sysvmsg);
3637
typedef struct {
3738
key_t key;
3839
zend_long id;
40+
zend_object std;
3941
} sysvmsg_queue_t;
4042

4143
struct php_msgbuf {
@@ -50,9 +52,6 @@ struct php_msgbuf {
5052
#define PHP_MSG_NOERROR 2
5153
#define PHP_MSG_EXCEPT 4
5254

53-
/* True global resources - no need for thread safety here */
54-
static int le_sysvmsg;
55-
5655
/* {{{ sysvmsg_module_entry
5756
*/
5857
zend_module_entry sysvmsg_module_entry = {
@@ -73,17 +72,58 @@ zend_module_entry sysvmsg_module_entry = {
7372
ZEND_GET_MODULE(sysvmsg)
7473
#endif
7574

76-
static void sysvmsg_release(zend_resource *rsrc)
75+
/* SysvMessageQueue class */
76+
77+
zend_class_entry *sysvmsg_queue_ce;
78+
static zend_object_handlers sysvmsg_queue_object_handlers;
79+
80+
static inline sysvmsg_queue_t *sysvmsg_queue_from_obj(zend_object *obj) {
81+
return (sysvmsg_queue_t *)((char *)(obj) - XtOffsetOf(sysvmsg_queue_t, std));
82+
}
83+
84+
#define Z_SYSVMSG_QUEUE_P(zv) sysvmsg_queue_from_obj(Z_OBJ_P(zv))
85+
86+
static zend_object *sysvmsg_queue_create_object(zend_class_entry *class_type) {
87+
sysvmsg_queue_t *intern = zend_object_alloc(sizeof(sysvmsg_queue_t), class_type);
88+
89+
zend_object_std_init(&intern->std, class_type);
90+
object_properties_init(&intern->std, class_type);
91+
intern->std.handlers = &sysvmsg_queue_object_handlers;
92+
93+
return &intern->std;
94+
}
95+
96+
static zend_function *sysvmsg_queue_get_constructor(zend_object *object) {
97+
zend_throw_error(NULL, "Cannot directly construct SysvMessageQueue, use msg_get_queue() instead");
98+
return NULL;
99+
}
100+
101+
static void sysvmsg_queue_free_obj(zend_object *object)
77102
{
78-
sysvmsg_queue_t *mq = (sysvmsg_queue_t *) rsrc->ptr;
79-
efree(mq);
103+
sysvmsg_queue_t *sysvmsg_queue = sysvmsg_queue_from_obj(object);
104+
105+
zend_object_std_dtor(&sysvmsg_queue->std);
80106
}
107+
/* }}} */
81108

82109
/* {{{ PHP_MINIT_FUNCTION
83110
*/
84111
PHP_MINIT_FUNCTION(sysvmsg)
85112
{
86-
le_sysvmsg = zend_register_list_destructors_ex(sysvmsg_release, NULL, "sysvmsg queue", module_number);
113+
zend_class_entry ce;
114+
INIT_CLASS_ENTRY(ce, "SysvMessageQueue", class_SysvMessageQueue_methods);
115+
sysvmsg_queue_ce = zend_register_internal_class(&ce);
116+
sysvmsg_queue_ce->ce_flags |= ZEND_ACC_FINAL;
117+
sysvmsg_queue_ce->create_object = sysvmsg_queue_create_object;
118+
sysvmsg_queue_ce->serialize = zend_class_serialize_deny;
119+
sysvmsg_queue_ce->unserialize = zend_class_unserialize_deny;
120+
121+
memcpy(&sysvmsg_queue_object_handlers, &std_object_handlers, sizeof(zend_object_handlers));
122+
sysvmsg_queue_object_handlers.offset = XtOffsetOf(sysvmsg_queue_t, std);
123+
sysvmsg_queue_object_handlers.free_obj = sysvmsg_queue_free_obj;
124+
sysvmsg_queue_object_handlers.get_constructor = sysvmsg_queue_get_constructor;
125+
sysvmsg_queue_object_handlers.clone_obj = NULL;
126+
87127
REGISTER_LONG_CONSTANT("MSG_IPC_NOWAIT", PHP_MSG_IPC_NOWAIT, CONST_PERSISTENT|CONST_CS);
88128
REGISTER_LONG_CONSTANT("MSG_EAGAIN", EAGAIN, CONST_PERSISTENT|CONST_CS);
89129
REGISTER_LONG_CONSTANT("MSG_ENOMSG", ENOMSG, CONST_PERSISTENT|CONST_CS);
@@ -103,7 +143,7 @@ PHP_MINFO_FUNCTION(sysvmsg)
103143
}
104144
/* }}} */
105145

106-
/* {{{ proto bool msg_set_queue(resource queue, array data)
146+
/* {{{ proto bool msg_set_queue(SysvMessageQueue queue, array data)
107147
Set information for a message queue */
108148
PHP_FUNCTION(msg_set_queue)
109149
{
@@ -113,13 +153,11 @@ PHP_FUNCTION(msg_set_queue)
113153

114154
RETVAL_FALSE;
115155

116-
if (zend_parse_parameters(ZEND_NUM_ARGS(), "ra", &queue, &data) == FAILURE) {
156+
if (zend_parse_parameters(ZEND_NUM_ARGS(), "Oa", &queue, sysvmsg_queue_ce, &data) == FAILURE) {
117157
RETURN_THROWS();
118158
}
119159

120-
if ((mq = (sysvmsg_queue_t *)zend_fetch_resource(Z_RES_P(queue), "sysvmsg queue", le_sysvmsg)) == NULL) {
121-
RETURN_THROWS();
122-
}
160+
mq = Z_SYSVMSG_QUEUE_P(queue);
123161

124162
if (msgctl(mq->id, IPC_STAT, &stat) == 0) {
125163
zval *item;
@@ -144,7 +182,7 @@ PHP_FUNCTION(msg_set_queue)
144182
}
145183
/* }}} */
146184

147-
/* {{{ proto array msg_stat_queue(resource queue)
185+
/* {{{ proto array msg_stat_queue(SysvMessageQueue queue)
148186
Returns information about a message queue */
149187
PHP_FUNCTION(msg_stat_queue)
150188
{
@@ -154,13 +192,11 @@ PHP_FUNCTION(msg_stat_queue)
154192

155193
RETVAL_FALSE;
156194

157-
if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &queue) == FAILURE) {
195+
if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &queue, sysvmsg_queue_ce) == FAILURE) {
158196
RETURN_THROWS();
159197
}
160198

161-
if ((mq = (sysvmsg_queue_t *)zend_fetch_resource(Z_RES_P(queue), "sysvmsg queue", le_sysvmsg)) == NULL) {
162-
RETURN_THROWS();
163-
}
199+
mq = Z_SYSVMSG_QUEUE_P(queue);
164200

165201
if (msgctl(mq->id, IPC_STAT, &stat) == 0) {
166202
array_init(return_value);
@@ -197,7 +233,7 @@ PHP_FUNCTION(msg_queue_exists)
197233
}
198234
/* }}} */
199235

200-
/* {{{ proto resource msg_get_queue(int key [, int perms])
236+
/* {{{ proto SysvMessageQueue msg_get_queue(int key [, int perms])
201237
Attach to a message queue */
202238
PHP_FUNCTION(msg_get_queue)
203239
{
@@ -209,7 +245,8 @@ PHP_FUNCTION(msg_get_queue)
209245
RETURN_THROWS();
210246
}
211247

212-
mq = (sysvmsg_queue_t *) emalloc(sizeof(sysvmsg_queue_t));
248+
object_init_ex(return_value, sysvmsg_queue_ce);
249+
mq = Z_SYSVMSG_QUEUE_P(return_value);
213250

214251
mq->key = key;
215252
mq->id = msgget(key, 0);
@@ -218,28 +255,25 @@ PHP_FUNCTION(msg_get_queue)
218255
mq->id = msgget(key, IPC_CREAT | IPC_EXCL | perms);
219256
if (mq->id < 0) {
220257
php_error_docref(NULL, E_WARNING, "Failed for key 0x" ZEND_XLONG_FMT ": %s", key, strerror(errno));
221-
efree(mq);
258+
zval_ptr_dtor(return_value);
222259
RETURN_FALSE;
223260
}
224261
}
225-
ZVAL_COPY_VALUE(return_value, zend_list_insert(mq, le_sysvmsg));
226262
}
227263
/* }}} */
228264

229-
/* {{{ proto bool msg_remove_queue(resource queue)
265+
/* {{{ proto bool msg_remove_queue(SysvMessageQueue queue)
230266
Destroy the queue */
231267
PHP_FUNCTION(msg_remove_queue)
232268
{
233269
zval *queue;
234270
sysvmsg_queue_t *mq = NULL;
235271

236-
if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &queue) == FAILURE) {
272+
if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &queue, sysvmsg_queue_ce) == FAILURE) {
237273
RETURN_THROWS();
238274
}
239275

240-
if ((mq = (sysvmsg_queue_t *)zend_fetch_resource(Z_RES_P(queue), "sysvmsg queue", le_sysvmsg)) == NULL) {
241-
RETURN_THROWS();
242-
}
276+
mq = Z_SYSVMSG_QUEUE_P(queue);
243277

244278
if (msgctl(mq->id, IPC_RMID, NULL) == 0) {
245279
RETVAL_TRUE;
@@ -249,7 +283,7 @@ PHP_FUNCTION(msg_remove_queue)
249283
}
250284
/* }}} */
251285

252-
/* {{{ proto mixed msg_receive(resource queue, int desiredmsgtype, int &msgtype, int maxsize, mixed &message [, bool unserialize=true [, int flags=0 [, int &errorcode]]])
286+
/* {{{ proto mixed msg_receive(SysvMessageQueue queue, int desiredmsgtype, int &msgtype, int maxsize, mixed &message [, bool unserialize=true [, int flags=0 [, int &errorcode]]])
253287
Send a message of type msgtype (must be > 0) to a message queue */
254288
PHP_FUNCTION(msg_receive)
255289
{
@@ -263,8 +297,8 @@ PHP_FUNCTION(msg_receive)
263297

264298
RETVAL_FALSE;
265299

266-
if (zend_parse_parameters(ZEND_NUM_ARGS(), "rlzlz|blz",
267-
&queue, &desiredmsgtype, &out_msgtype, &maxsize,
300+
if (zend_parse_parameters(ZEND_NUM_ARGS(), "Olzlz|blz",
301+
&queue, sysvmsg_queue_ce, &desiredmsgtype, &out_msgtype, &maxsize,
268302
&out_message, &do_unserialize, &flags, &zerrcode) == FAILURE) {
269303
RETURN_THROWS();
270304
}
@@ -291,9 +325,7 @@ PHP_FUNCTION(msg_receive)
291325
}
292326
}
293327

294-
if ((mq = (sysvmsg_queue_t *)zend_fetch_resource(Z_RES_P(queue), "sysvmsg queue", le_sysvmsg)) == NULL) {
295-
RETURN_THROWS();
296-
}
328+
mq = Z_SYSVMSG_QUEUE_P(queue);
297329

298330
messagebuffer = (struct php_msgbuf *) safe_emalloc(maxsize, 1, sizeof(struct php_msgbuf));
299331

@@ -335,7 +367,7 @@ PHP_FUNCTION(msg_receive)
335367
}
336368
/* }}} */
337369

338-
/* {{{ proto bool msg_send(resource queue, int msgtype, mixed message [, bool serialize=true [, bool blocking=true [, int errorcode]]])
370+
/* {{{ proto bool msg_send(SysvMessageQueue queue, int msgtype, mixed message [, bool serialize=true [, bool blocking=true [, int errorcode]]])
339371
Send a message of type msgtype (must be > 0) to a message queue */
340372
PHP_FUNCTION(msg_send)
341373
{
@@ -349,14 +381,12 @@ PHP_FUNCTION(msg_send)
349381

350382
RETVAL_FALSE;
351383

352-
if (zend_parse_parameters(ZEND_NUM_ARGS(), "rlz|bbz",
353-
&queue, &msgtype, &message, &do_serialize, &blocking, &zerror) == FAILURE) {
384+
if (zend_parse_parameters(ZEND_NUM_ARGS(), "Olz|bbz",
385+
&queue, sysvmsg_queue_ce, &msgtype, &message, &do_serialize, &blocking, &zerror) == FAILURE) {
354386
RETURN_THROWS();
355387
}
356388

357-
if ((mq = (sysvmsg_queue_t *)zend_fetch_resource(Z_RES_P(queue), "sysvmsg queue", le_sysvmsg)) == NULL) {
358-
RETURN_THROWS();
359-
}
389+
mq = Z_SYSVMSG_QUEUE_P(queue);
360390

361391
if (do_serialize) {
362392
smart_str msg_var = {0};

ext/sysvmsg/sysvmsg.stub.php

+15-25
Original file line numberDiff line numberDiff line change
@@ -2,30 +2,20 @@
22

33
/** @generate-function-entries */
44

5-
/** @return resource|false */
6-
function msg_get_queue(int $key, int $perms = 0666) {}
7-
8-
/**
9-
* @param resource $queue
10-
*/
11-
function msg_send($queue, int $msgtype, $message, bool $serialize = true, bool $blocking = true, &$errorcode = null): bool {}
12-
13-
/**
14-
* @param resource $queue
15-
*/
16-
function msg_receive($queue, int $desiredmsgtype, &$msgtype, int $maxsize, &$message, bool $unserialize = true, int $flags = 0, &$errorcode = null): bool {}
17-
18-
/**
19-
* @param resource $queue
20-
*/
21-
function msg_remove_queue($queue): bool {}
22-
23-
/** @param resource $queue */
24-
function msg_stat_queue($queue): array|false {}
25-
26-
/**
27-
* @param resource $queue
28-
*/
29-
function msg_set_queue($queue, array $data): bool {}
5+
final class SysvMessageQueue
6+
{
7+
}
8+
9+
function msg_get_queue(int $key, int $perms = 0666): SysvMessageQueue|false {}
10+
11+
function msg_send(SysvMessageQueue $queue, int $msgtype, $message, bool $serialize = true, bool $blocking = true, &$errorcode = null): bool {}
12+
13+
function msg_receive(SysvMessageQueue $queue, int $desiredmsgtype, &$msgtype, int $maxsize, &$message, bool $unserialize = true, int $flags = 0, &$errorcode = null): bool {}
14+
15+
function msg_remove_queue(SysvMessageQueue $queue): bool {}
16+
17+
function msg_stat_queue(SysvMessageQueue $queue): array|false {}
18+
19+
function msg_set_queue(SysvMessageQueue $queue, array $data): bool {}
3020

3121
function msg_queue_exists(int $key): bool {}

ext/sysvmsg/sysvmsg_arginfo.h

+11-6
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
/* This is a generated file, edit the .stub.php file instead. */
22

3-
ZEND_BEGIN_ARG_INFO_EX(arginfo_msg_get_queue, 0, 0, 1)
3+
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_msg_get_queue, 0, 1, SysvMessageQueue, MAY_BE_FALSE)
44
ZEND_ARG_TYPE_INFO(0, key, IS_LONG, 0)
55
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, perms, IS_LONG, 0, "0666")
66
ZEND_END_ARG_INFO()
77

88
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_msg_send, 0, 3, _IS_BOOL, 0)
9-
ZEND_ARG_INFO(0, queue)
9+
ZEND_ARG_OBJ_INFO(0, queue, SysvMessageQueue, 0)
1010
ZEND_ARG_TYPE_INFO(0, msgtype, IS_LONG, 0)
1111
ZEND_ARG_INFO(0, message)
1212
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, serialize, _IS_BOOL, 0, "true")
@@ -15,7 +15,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_msg_send, 0, 3, _IS_BOOL, 0)
1515
ZEND_END_ARG_INFO()
1616

1717
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_msg_receive, 0, 5, _IS_BOOL, 0)
18-
ZEND_ARG_INFO(0, queue)
18+
ZEND_ARG_OBJ_INFO(0, queue, SysvMessageQueue, 0)
1919
ZEND_ARG_TYPE_INFO(0, desiredmsgtype, IS_LONG, 0)
2020
ZEND_ARG_INFO(1, msgtype)
2121
ZEND_ARG_TYPE_INFO(0, maxsize, IS_LONG, 0)
@@ -26,15 +26,15 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_msg_receive, 0, 5, _IS_BOOL, 0)
2626
ZEND_END_ARG_INFO()
2727

2828
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_msg_remove_queue, 0, 1, _IS_BOOL, 0)
29-
ZEND_ARG_INFO(0, queue)
29+
ZEND_ARG_OBJ_INFO(0, queue, SysvMessageQueue, 0)
3030
ZEND_END_ARG_INFO()
3131

3232
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_msg_stat_queue, 0, 1, MAY_BE_ARRAY|MAY_BE_FALSE)
33-
ZEND_ARG_INFO(0, queue)
33+
ZEND_ARG_OBJ_INFO(0, queue, SysvMessageQueue, 0)
3434
ZEND_END_ARG_INFO()
3535

3636
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_msg_set_queue, 0, 2, _IS_BOOL, 0)
37-
ZEND_ARG_INFO(0, queue)
37+
ZEND_ARG_OBJ_INFO(0, queue, SysvMessageQueue, 0)
3838
ZEND_ARG_TYPE_INFO(0, data, IS_ARRAY, 0)
3939
ZEND_END_ARG_INFO()
4040

@@ -62,3 +62,8 @@ static const zend_function_entry ext_functions[] = {
6262
ZEND_FE(msg_queue_exists, arginfo_msg_queue_exists)
6363
ZEND_FE_END
6464
};
65+
66+
67+
static const zend_function_entry class_SysvMessageQueue_methods[] = {
68+
ZEND_FE_END
69+
};

ext/sysvmsg/tests/003.phpt

+2-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ echo "Done\n";
1818
?>
1919
--EXPECTF--
2020
bool(false)
21-
resource(%d) of type (sysvmsg queue)
21+
object(SysvMessageQueue)#1 (0) {
22+
}
2223
bool(true)
2324
bool(true)
2425
bool(false)

0 commit comments

Comments
 (0)