Reputation: 2060
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:
ier = ..
)return
statements in the code, removing the return
statementsIt 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
Upvotes: 8
Views: 460
Reputation: 1017
Your program, seems, currupts the stack. Stack corruption usually comes with improper usage of pointers. Check carefully (investigate contents of variables using debugger or simple footprints) right before suspicious function calls.
Upvotes: 1
Reputation: 2060
Took a while, and needed additional help (issues like this)
Basically two things had to change:
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!
Upvotes: 2