从C调用Perl函数会导致崩溃

时间:2015-03-16 10:54:08

标签: c multithreading perl

我有一个用C语言编写的Perl库,在XS文件中我声明了回调函数来从C代码调用Perl函数。从C代码(多线程)调用此函数时:

char *
callbackfunc(void *fun, char **args)
{
  dSP;

  int count,i;
  char *s;

  ENTER;
  SAVETMPS;

  PUSHMARK(SP);
  for(i=0;args[i];++i) {
    XPUSHs(sv_2mortal(newSVpv(args[i],0)));
  }
  PUTBACK;

  count = call_sv(fun,G_SCALAR|G_EVAL);

  SPAGAIN;

  s = NULL;
  if(count > 1)
    croak("callback may return only single value\n");
  if(count==1) {
    s = strdup(POPp);
  }

  PUTBACK;
  FREETMPS;
  LEAVE;    
  return s;
}

我在 dSP 宏崩溃了:

#0 callbackfunc (fun=0x2416a58, args=0x7f3a0cfa9a10) at MyLibrary.xs:24
24 dSP;

在反汇编程序中,它看起来像找不到某些特定于线程的数据:

push  %r15
push  %r14
mov   %rdi,%r14
push  %r13
mov   %rsi,%r13
push  %r12
push  %rbp
push  %rbx
sub   $0x8,%rsp
mov   0x2015dd(%rip),%rbx
mov   (%rbx),%edi
callq 0x7f3a0e37f550 <pthread_getspecific@plt>
mov   (%rbx),%esi
mov   (%rax),%r15 // here is crash because %rax is 0x0

1 个答案:

答案 0 :(得分:2)

你可能忘了告诉你的线程当前的Perl解释器。 perlembed man page说:

  只要没有创建interp的线程使用interp(使用perl_alloc()或更深奥的perl_clone()),也应该调用PERL_SET_CONTEXT(interp)。

另请注意,从C调用Perl不是线程安全的。确保正确锁定。

编辑:如果您没有自己创建解释器,则可以通过宏void *向解释器获取PERL_GET_CONTEXT。如果您只使用单个解释器,则可以向XS引导部分添加一些代码,以将此值存储在全局中。如果您有多个解释器(或希望在Windows上支持fork),则必须在注册回调时跟踪当前的解释器。