Re: Segfault

php.internals

RG

20 years ago
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!"); }

Sara Golemon

20 years ago
> 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

RG

20 years ago
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.

RG

20 years ago
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.

Sara Golemon

20 years ago
> 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

20 years ago
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

RG

20 years ago
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

Hartmut Holzgraefe

20 years ago
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 :(

RG

20 years ago
> 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.

Sara Golemon

20 years ago
> 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;