0
回答
mysql的udf函数中使用信号量操作触发段错误
利用AWS快速构建适用于生产的无服务器应用程序,免费试用12个月>>>   

最近想使用mysql的udf函数通过信号量与另外一个进程进行同步,信号量初始化为1(sem_reset),该进程阻塞等待信号量变为0(sem_wait)后唤醒执行一些逻辑,然后信号量再被恢复为1(sem_reset),如此循环往复。在mysql的udf函数当中没有使用信号量的阻塞操作,只是在一定条件下将信号量更新为0(sem_post),唤醒这个进程。 

结果在另外进程阻塞等待信号量变化为0时,触发mysql的udf函数然后执行到sem_post调用之后,mysql就直接crash了:ERROR 2013 (HY000): Lost connection to MySQL server during query。mysql的错误日志里面显示是收到了信号11,应该是个段错误。将sem_post调用注释掉之后这个bug就不会出现,重复测试了多次。

单独写了两份和mysql无关的测试代码,一份和上述阻塞等待进程相同,一份主动调用sem_post函数唤醒等待进程,分别编译为两个进程进行测试,没有触发任何错误,等待进程被正常唤醒。

信号量相关操作代码如下:

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/sem.h>
#include "mysql/mysql.h"

typedef union
{
    int val;
    struct semid_ds *buf;
    unsigned short int *array;
    struct seminfo *__buf;
} sem_ctl_u;

//阻塞等待信号量

int sem_wait(int sem_id)

{
    struct sembuf sem_b = { 0, 0, 0 }; //blocking for 0
    if(semop(sem_id, &sem_b, 1) == -1)
    {
        fprintf(stderr, "semaphore wait failed: %s\n", strerror(errno));
        return 0;
    }
    return 1;
}

//信号量初始化
int sem_reset(int sem_id)
{
    sem_ctl_u sem_arg;
    sem_arg.val = 1;
    if (semctl(sem_id, 0, SETVAL, sem_arg) == -1)
    {
        fprintf(stderr, "Semaphore reset failed: %s\n", strerror(errno));
        return 0;
    }
    return 1;
}

//信号量投递
int sem_post(int sem_id)
{
    sem_ctl_u sem_arg;
    sem_arg.val = 0;
    if (semctl(sem_id, 0, SETVAL, sem_arg) == -1)
    {
        fprintf(stderr, "Semaphore post failed: %s\n", strerror(errno));
        return 0;
    }
    return 1;
}

mysql错误日志信息如下:

140421 11:04:18 [Note] /usr/sbin/mysqld: ready for connections.

Version: '5.5.35-0ubuntu0.12.04.2'  socket: '/var/run/mysqld/mysqld.sock'  port: 3306  (Ubuntu)
03:41:39 UTC - mysqld got signal 11 ;
This could be because you hit a bug. It is also possible that this binary
or one of the libraries it was linked against is corrupt, improperly built,
or misconfigured. This error can also be caused by malfunctioning hardware.
We will try our best to scrape up some info that will hopefully help
diagnose the problem, but since we have already crashed,
something is definitely wrong and this may fail.


key_buffer_size=16777216
read_buffer_size=131072
max_used_connections=1
max_threads=151
thread_count=1
connection_count=1
It is possible that mysqld could use up to
key_buffer_size + (read_buffer_size + sort_buffer_size)*max_threads = 346075 K  bytes of memory
Hope that's ok; if not, decrease some variables in the equation.


Thread pointer: 0xffffffffb94a5e60
Attempting backtrace. You can use the following information to find out
where mysqld died. If you see no messages after this, something went
terribly wrong...
stack_bottom = ffffffffb623f2cc thread_stack 0x30000
/usr/sbin/mysqld(my_print_stacktrace+0x33)[0xb72b5a43]
/usr/sbin/mysqld(handle_fatal_signal+0x484)[0xb7161fa4]
[0xb6e15400]
/usr/sbin/mysqld(_ZN13Item_udf_func7cleanupEv+0x42)[0xb71b3e22]
/usr/sbin/mysqld(_ZN3THD19cleanup_after_queryEv+0x88)[0xb6ffcc88]
/usr/sbin/mysqld(_Z11mysql_parseP3THDPcjP12Parser_state+0x168)[0xb702fec8]
/usr/sbin/mysqld(_Z16dispatch_command19enum_server_commandP3THDPcj+0x236b)[0xb703229b]
/usr/sbin/mysqld(_Z10do_commandP3THD+0xd3)[0xb7032ce3]
/usr/sbin/mysqld(_Z24do_handle_one_connectionP3THD+0x1eb)[0xb70e6bdb]
/usr/sbin/mysqld(handle_one_connection+0x50)[0xb70e6c40]
/lib/i386-linux-gnu/libpthread.so.0(+0x6d4c)[0xb6d8cd4c]
/lib/i386-linux-gnu/libc.so.6(clone+0x5e)[0xb6b9bace]


Trying to get some variables.
Some pointers may be invalid and cause the dump to abort.
Query (ffffffffa6b2ce40): is an invalid pointer
Connection ID (thread ID): 40
                                      
-----------------------------------------------------------------------------------------------------------------

测试环境是ubuntu 12.04.2,mysql版本是5.5.35。

不知道是mysql的udf函数是设计如此,不允许使用信号量操作,还是mysql的bug,或者我自身的代码有问题。还请大牛给指点!


举报
socoding
发帖于4年前 0回/300阅
顶部