The following code segfaults after either I call die/exit or call
socketi_accept once again.
Can anyone spot anything working with it?
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "php.h"
#include "php_hello.h"
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <errno.h>
#define IS_INVALID_SOCKET(a) (a->bsd_socket < 0)
#define set_errno(a) (errno = a)
static
ZEND_BEGIN_ARG_INFO(second_and_third_args_force_ref, 0)
ZEND_ARG_PASS_INFO(0)
ZEND_ARG_PASS_INFO(1)
ZEND_ARG_PASS_INFO(1)
ZEND_END_ARG_INFO();
static int le_socket = -1;
#define le_socket_name "Socket"
static socklen_t s_len = sizeof(struct sockaddr);
static function_entry hello_functions[] = {
PHP_FE(hello_world, first_arg_force_ref)
PHP_FE(socketi_accept, second_and_third_args_force_ref)
{NULL, NULL, NULL}
};
/*--- */
PHP_MINFO_FUNCTION(hello)
{
php_info_print_table_start();
php_info_print_table_row(2, "Sockets Improved Support", "enabled");
php_info_print_table_end();
}
PHP_RINIT_FUNCTION(hello)
{
return SUCCESS;
}
PHP_RSHUTDOWN_FUNCTION(hello)
{
return SUCCESS;
}
/----/
PHP_MINIT_FUNCTION(hello);
zend_module_entry hello_module_entry = {
#if ZEND_MODULE_API_NO >= 20010901
STANDARD_MODULE_HEADER,
#endif
PHP_HELLO_WORLD_EXTNAME,
hello_functions,
PHP_MINIT(hello),
NULL,
PHP_RINIT(hello),
PHP_RSHUTDOWN(hello),
PHP_MINFO(hello),
#if ZEND_MODULE_API_NO >= 20010901
PHP_HELLO_WORLD_VERSION,
#endif
STANDARD_MODULE_PROPERTIES
};
#ifdef COMPILE_DL_HELLO
ZEND_GET_MODULE(hello)
#endif
#define PHP_SOCKETS_API
#if HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
typedef int PHP_SOCKET;
typedef struct {
PHP_SOCKET bsd_socket;
int type;
int error;
} php_socket;
#define le_socket_name "Socket"
//static int le_socket = 0;
static void php_destroy_socket(zend_rsrc_list_entry *rsrc TSRMLS_DC)
{
php_socket *php_sock = (php_socket *) rsrc->ptr;
close(php_sock->bsd_socket);
efree(php_sock);
}
PHP_MINIT_FUNCTION(hello)
{
le_socket = zend_fetch_list_dtor_id("Socket");
//le_socket = zend_register_list_destructors_ex(, NULL, le_socket_name,
module_number);
}
ZEND_BEGIN_MODULE_GLOBALS(hello)
int last_error;
char *strerror_buf;
ZEND_END_MODULE_GLOBALS(hello)
PHP_FUNCTION(hello_world)
{
zend_printf("%d--\n", le_socket);
zval *buf;
char *recv_buf;
int retval, len;
long test;
// long len, flags, php_sock_res;
// if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lzll",
&php_sock_res, &buf, &len, &flags) == FAILURE)
// return;
test = NULL;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|l", &buf,
&test) == FAILURE)
return;
if(test != NULL)
zend_printf("%ld", test);
len = 300;
recv_buf = emalloc(len + 1);
memset(recv_buf, '\0', len + 1);
// retval = recvz(recv_buf);
char new_set[] = "=D!!";
retval = strlen(new_set);
memcpy(recv_buf, new_set, retval);
recv_buf[retval] = '\0';
zval_dtor(buf);
Z_STRVAL_P(buf) = recv_buf;
Z_STRLEN_P(buf) = retval;
Z_TYPE_P(buf) = IS_STRING;
zend_printf("(((((----------- %d -------------))))))))))", le_socket);
RETURN_LONG(retval);
}
PHP_FUNCTION(socketi_accept)
{
zend_printf("[init]");
zval *sock, *remote_addr, *port;
php_socket *php_sock, *new_sock;
struct sockaddr_in sa;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|zz", &sock,
&remote_addr, &port) == FAILURE)
return;
ZEND_FETCH_RESOURCE(php_sock, php_socket *, &sock, -1, le_socket_name,
le_socket);
int salen, addr_len;
salen = sizeof(struct sockaddr_in);
new_sock->bsd_socket = accept(php_sock->bsd_socket, &sa, &salen);
switch(ZEND_NUM_ARGS())
{
case 3:
{
Z_TYPE_P(port) = IS_LONG;
Z_LVAL_P(port) = ntohs(sa.sin_port);
}
case 2:
{
char *buf;
addr_len = strlen(inet_ntoa(sa.sin_addr));
buf = (char *) emalloc(addr_len + 1);
zend_printf("[1]");
memcpy(buf, inet_ntoa(sa.sin_addr), addr_len);
zend_printf("[2]");
buf[addr_len] = '\0';
zval_dtor(remote_addr);
zend_printf("[3]");
Z_STRVAL_P(remote_addr) = buf;
Z_STRLEN_P(remote_addr) = addr_len;
Z_TYPE_P(remote_addr) = IS_STRING;
efree(buf);
}
default: //don't ask me how
case 1:
zend_printf("[4]");
new_sock->error = 0;
zend_printf("[5]");
}
ZEND_REGISTER_RESOURCE(return_value, new_sock, le_socket);
zend_printf("RET!");
}
new_sock->bsd_socket = accept(php_sock->bsd_socket, &sa, &salen);
In all liklihood it's that.
Now.... In the nicest way possible, why don't I suggest that you CLEAN UP
YOUR CODE NEXT TIME!?!?! You might have noticed that new_sock isn't alloc'd
if it wern't for all the comments and flat-out bad code you've got in there.
Thank you for calling, next in line please.
-Sara
For some reason I can't malloc php_socket structs, and that's not where it
segfaults. The function works perfectly once. Then if I attempt to exit /
die or call that function again, it dies.
""Sara Golemon"" pollita@php.net wrote in message
news:00f301c5ba49$455192c0$5c8be5a9@ohr.berkeley.edu...
new_sock->bsd_socket = accept(php_sock->bsd_socket, &sa, &salen);
In all liklihood it's that.
Now.... In the nicest way possible, why don't I suggest that you CLEAN UP
YOUR CODE NEXT TIME!?!?! You might have noticed that new_sock isn't
alloc'd
if it wern't for all the comments and flat-out bad code you've got in
there.Thank you for calling, next in line please.
-Sara
That's not where it segfaults. The function works perfectly once. If I
attempt to exit /
die or call that function again, it segfaults.
However, I have noticed that if I do not use ZEND_REGISTER_RESOURCE the
program no longer segfaults.
And sorry for the comments, someone people don't write the final version of
a program on their first try.
""Sara Golemon"" pollita@php.net wrote in message
news:00f301c5ba49$455192c0$5c8be5a9@ohr.berkeley.edu...
new_sock->bsd_socket = accept(php_sock->bsd_socket, &sa, &salen);
In all liklihood it's that.
Now.... In the nicest way possible, why don't I suggest that you CLEAN UP
YOUR CODE NEXT TIME!?!?! You might have noticed that new_sock isn't
alloc'd
if it wern't for all the comments and flat-out bad code you've got in
there.Thank you for calling, next in line please.
-Sara
That's not where it segfaults. The function works perfectly once. If I
attempt to exit /
die or call that function again, it segfaults.
However, I have noticed that if I do not use ZEND_REGISTER_RESOURCE the
program no longer segfaults.
I didn't say that's where it segfaults, I said that's where your problem is.
Just because you can write to a particular memory location once doesn't
change the fact that the memory in question doesn't belong to your new_sock
struct. Your code is tacking a relevant piece of data and just throwing it
out into the middle of the memory pool hoping it doesn't hit some swimmer in
the head in the process. Figure out why you can't malloc the struct first.
That one is a very clear, unambiguous crash-causing bug.
And sorry for the comments, someone people don't write the final version
of
a program on their first try.
I'd doubt anyone does. Writing well-indented code helps debugging though
(both for you and for people you ask to take a second look). Right now it's
all just cluttered. As my momma always told me, "If you'd clean up your
room once in awhile, you might find what you're looking for."
And if my reply sounded harsh, it might have to do with the fact that you
ignored my suggestions on how to implement zend_fetch_list_dtor_id().
-Sara
Well I did try to use it in RINIT, but PHP just wasn't RINIT.... so I
figured why not put it in MINIT
""Sara Golemon"" pollita@php.net wrote in message
news:001901c5ba69$b6573c70$6c051fac@lighthammer...
That's not where it segfaults. The function works perfectly once. If I
attempt to exit /
die or call that function again, it segfaults.
However, I have noticed that if I do not use ZEND_REGISTER_RESOURCE the
program no longer segfaults.I didn't say that's where it segfaults, I said that's where your problem
is.
Just because you can write to a particular memory location once doesn't
change the fact that the memory in question doesn't belong to your
new_sock
struct. Your code is tacking a relevant piece of data and just throwing
it
out into the middle of the memory pool hoping it doesn't hit some swimmer
in
the head in the process. Figure out why you can't malloc the struct
first.
That one is a very clear, unambiguous crash-causing bug.And sorry for the comments, someone people don't write the final version
of
a program on their first try.I'd doubt anyone does. Writing well-indented code helps debugging though
(both for you and for people you ask to take a second look). Right now
it's
all just cluttered. As my momma always told me, "If you'd clean up your
room once in awhile, you might find what you're looking for."And if my reply sounded harsh, it might have to do with the fact that you
ignored my suggestions on how to implement zend_fetch_list_dtor_id().-Sara
Well I did try to use it in RINIT, but PHP just wasn't RINIT.... so I
figured why not put it in MINIT. And I solved the problem, I guess I should
have been more careful when reading the PHP API tutorials, I used malloc
instead of emalloc, so malloc was causing gcc to miscalculate its size or
make it quit with an error. Thank you for your help.
""Sara Golemon"" pollita@php.net wrote in message
news:001901c5ba69$b6573c70$6c051fac@lighthammer...
That's not where it segfaults. The function works perfectly once. If I
attempt to exit /
die or call that function again, it segfaults.
However, I have noticed that if I do not use ZEND_REGISTER_RESOURCE the
program no longer segfaults.I didn't say that's where it segfaults, I said that's where your problem
is.
Just because you can write to a particular memory location once doesn't
change the fact that the memory in question doesn't belong to your
new_sock
struct. Your code is tacking a relevant piece of data and just throwing
it
out into the middle of the memory pool hoping it doesn't hit some swimmer
in
the head in the process. Figure out why you can't malloc the struct
first.
That one is a very clear, unambiguous crash-causing bug.And sorry for the comments, someone people don't write the final version
of
a program on their first try.I'd doubt anyone does. Writing well-indented code helps debugging though
(both for you and for people you ask to take a second look). Right now
it's
all just cluttered. As my momma always told me, "If you'd clean up your
room once in awhile, you might find what you're looking for."And if my reply sounded harsh, it might have to do with the fact that you
ignored my suggestions on how to implement zend_fetch_list_dtor_id().-Sara
RG wrote:
Well I did try to use it in RINIT, but PHP just wasn't RINIT.... so I
figured why not put it in MINIT.
...
I used malloc
instead of emalloc, so malloc was causing gcc to miscalculate its size or
make it quit with an error.
both claims above don't make any sense to me, making me think
you still really do not know what you are doing :(
both claims above don't make any sense to me, making me think
you still really do not know what you are doing :(
O_O, wow, sorry...
I did not write that like that......
What I meant to say was that I did use zend_fetch_list_dtor_id in RINIT at
first, but I noticed that PHP was not calling RINIT. So then I migrated it
MINIT, which is called when the module is loaded.
As for malloc/emalloc, I tried using malloc(sizeof(struct php_socket));
which did not work because gcc was erroring with "Incomplete datatype". I
then re-read the Zend API function list and came across emalloc, which I had
omitted when I first read it. So once I used emalloc, it worked.
What I meant to say was that I did use zend_fetch_list_dtor_id in RINIT
at
first, but I noticed that PHP was not calling RINIT. So then I migrated it
MINIT, which is called when the module is loaded.
Doubtful... PHP calls every module's RINIT at the start of every request.
If you were "testing" RINIT by launching something like php -m
or php -i
or something then sure RINIT wouldn't be called. There's no actual request
involved. In a real script execute it most certainly would call RINIT.
As for malloc/emalloc, I tried using malloc(sizeof(struct php_socket));
which did not work because gcc was erroring with "Incomplete datatype". I
then re-read the Zend API function list and came across emalloc, which I
had
omitted when I first read it. So once I used emalloc, it worked.
The malloc/emalloc issue is genuine enough in that yes, you do need to be
using the emalloc() family over the system malloc allocators (except in rare
cases involving persistency).
The larger issue of the incomplete type comes from the fact that the form of
your structure declaration means you'll want to get your size from
sizeof(php_socket) not sizeof(struct php_socket).
typedef struct {
PHP_SOCKET bsd_socket;
int type;
int error;
} php_socket;