SEG Fault in PHP extension
c, php, php-extension, php-internals, segmentation-fault
Solution
Took a while, and needed additional help (issues like this)
Basically two things had to change:
- Pass integers by reference
- Accept strings properly
The first is easy, simply `ier=func(..., &integer_var, ...)`
The second involved passing the length of the string. There may have been an easier way to do this (sensing string length by looking for the \0) but they didn't work out. So, now I pass
ier = func(str,strlen,...)
Then in Fortran, I accept the string as
character(kind=c_char,len=strlen), intent(IN) :: str
The specific changes to the fortran code above are
11 use, intrinsic :: iso_c_binding
12 use interfaces_rmnutils
13 implicit none
16 integer(kind=c_int), intent(IN) :: len_filA, len_filB, len_filO
17 character (kind=c_char,len=len_filA), intent(IN) :: filA
18 character (kind=c_char,len=len_filB), intent(IN) :: filB
19 character (kind=c_char,len=len_filO), intent(IN) :: filO
When it was working, it must have been before I attempted to read in the strings as `(len=*)`, and integers were being passed in as references, so they'd have had random values essentially.
Thanks for everyone's else!
Problem
I wrote a PHP extension to access functions in a static lib, I built PHP as a CGI, and everything seemed to work (after days of working on it..) Thrilled once everything worked, I re-compiled PHP without debugging messages I had in it. (`php_printf("here111");` .... `php_printf("sending arguments...");`) Then, it just stopped working. The function I'm calling in the static lib works, I've tested it by calling it directly from another executable. I built PHP with debugging symbols (`--enable-debug`) and can debug it to a certain degree in gdb. I'm still struggling to figure out what's wrong. It seems that the function in the lib (`diffFst`) cannot seem to read the input arguments. ``` 268 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ssssssd", 269 &filA, &filA_len, 270 &nomvarA, &nomvarA_len, 271 &filB, &filB_len, 272 &nomvarB, &nomvarB_len, 273 &filO, &filO_len, 274 &newnomvar, &newnomvar_len, 275 &mult 276 ) == FAILURE) { 277 RETURN_LONG(-100); 278 } 279 280 php_printf("Read arguments:\nfilA: %s, nomvara: %s\nfilB: %s, nomvarB: %s\nfilO: %s, nomvarO: %s\nMult: %0.3f\n", 281 filA,nomvarA, filB,nomvarB, filO,newnomvar, mult); 282 285 ier = difffst_(filA,nomvarA, filB,nomvarB, filO,newnomvar, mult); ``` When I call this function, the `php_printf()` statement works and prints out the right values. When I let it call the difffst_ function however, I get a segfault when it tries to read the input variables. The diffFst function is written in fortran: ``` 5 function diffFst(filA, nomvara, filB, nomvarb, filO, newnomvar, change, write_tictac, in_verbose) result(ier) 10 implicit none 11 12 character (len=*), intent(IN) :: filA, filB, filO 13 character (len=*), intent(IN) :: nomvara, nomvarb, newnomvar 14 16 real, intent(IN) :: change 17 logical, intent(IN) :: write_tictac 18 19 logical, intent(IN), optional :: in_verbose 21 logical :: verbose = .false. 27 integer :: ier ... 117 ier = fstouv(iuna, 'RND') 118 IF (ier < 0) THEN 119 if (verbose) write(stderr,'(2A)') "Could not fstouv FST file ", trim(filA) 120 ELSE 121 nmax = fstnbr(iuna); 122 if (verbose) write(stdout,'(3A,I6,A)') "Succesfully opened ", trim(filA), ' with ', nmax, ' records' 123 allocate(liste(nmax)) 124 END IF ``` Specifically, it fails at line 122 (according to the debugger) when it tries to read `filA`. I have no idea why, I've tried: - Making the function a subroutine - Making the function a fortran function - Making the function a 'pure' function - Having return values (that's what is there now, the `ier = ..`) - Having `return` statements in the code, removing the `return` statements - Tried printing things out to stdout, and to log files It just seems like the data isn't being passed properly. Even in the debugger, I can't read the arguments. The frustrating thing is, at one point this just worked.. I've checked file permissions, checked paths, etc.. And I can run the function from a fortran wrapper executable just fine. Is there a trick I'm missing? Thanks