【问题标题】:Can someone trace the reason for segmentation fault?有人可以追踪分段错误的原因吗?
【发布时间】:2021-06-10 03:28:51
【问题描述】:
public class Watcher: Object
{
    private int _fd;
    private uint _watch;
    private IOChannel _channel;
    private uint8[] _buffer;
    private int BUFFER_LENGTH;

    public Watcher(string path, Linux.InotifyMaskFlags mask){

        _buffer = new uint8[BUFFER_LENGTH];

        //➔ Initialize notify subsystem
        _fd = Linux.inotify_init(); 
        
        if(_fd < 0){
            error(@"Failed to initialize the notify subsystem: $(strerror(errno))");
        }

        //➔ actually adding abstraction to linux file descriptor
        _channel = new IOChannel.unix_new(_fd);
        
        //➔ watch the channel for given condition
        //➔ IOCondition.IN => When the channel is ready for reading , IOCondition.HUP=>Hangup(Error)
        _watch = _channel.add_watch(IOCondition.IN | IOCondition.HUP, onNotified);

        if(_watch < 0){
            error(@"Failed to add watch to channel");
        }

        //➔ Tell linux kernel to watch for any mask(for ex; access, modify) on a given filepath
    
        var ok = Linux.inotify_add_watch(_fd, path, mask);
        if(ok < 0){
            error(@"Failed to add watch to path -- $path : $(strerror(errno))");
        }
        print(@"Watching for $(mask) on $path");

    }
    protected bool onNotified(IOChannel src, IOCondition condition)
    {
        if( (condition & IOCondition.HUP) == IOCondition.HUP){
            error(@"Received hang up from inotify, can't get update");
        }
        if( (condition & IOCondition.IN) == IOCondition.IN){
            
            var bytesRead = Posix.read(_fd, _buffer, BUFFER_LENGTH);

            Linux.InotifyEvent *pevent = (Linux.InotifyEvent*) _buffer;

            handleEvent(*pevent);
        }
        return true;
    }

    protected void handleEvent(Linux.InotifyEvent ev){
        print("Access Detected!\n");
        Posix.exit(0);
    }
    ~Watcher(){
        if(_watch != 0){
            Source.remove(_watch);
        }
        if(_fd != -1){
            Posix.close(_fd);
        }
    }
}
int main(string[] args) requires (args.length > 1)
{
    var watcher = new Watcher(args[1], Linux.InotifyMaskFlags.ACCESS);

    var loop = new MainLoop();

    loop.run();

    return 0;
}

上面的代码可以在“Vala Programming 简介 - Michael Lauer”中找到

失败证明: Image displaying failure on access to the file being watched for access

1 号航站楼: ./inotifyWatcher 2号航站楼: 猫

只要我访问该文件,就会发生分段错误。 我也尝试过使用 gdb 作为失败的原因,但这对我来说大多是神秘的。我在我的机器上使用 parrot(debian/64-bit)。另外,我是新手(stackoverflow,linux内核程序)。

【问题讨论】:

    标签: linux vala inotify


    【解决方案1】:

    使用--debug 开关编译时,Vala 源代码行号可以包含在二进制文件中。行号出现在.debug_lineDWARF section of an ELF binary:

    valac --debug --pkg linux inotifyWatcher.vala
    

    在第一个终端中使用gdb 运行二进制文件:

    gdb --args ./inotifyWatcher .
    (gdb) run
    

    点指定监视当前目录。然后,当使用ls 之类的命令访问当前目录时,观察程序分段错误。 GDB 的输出是:

    Program received signal SIGSEGV, Segmentation fault.
    0x0000000000401a86 in watcher_onNotified (self=0x412830, src=0x40e6e0, condition=G_IO_IN) at inotifyWatcher.vala:51
    51              handleEvent(*pevent);
    

    GDB 包含源文件中的行号 51 并显示该行。

    所以问题在于从文件描述符中读取然后将缓冲区传递给handleEvent。您可能想检查 bytesRead 是否大于零,我不确定在此示例中使用指针。像这样的显式指针很少需要在 Vala 中使用,它可能需要更改绑定,例如使用ref修改参数的传递方式。

    【讨论】:

      猜你喜欢
      • 2023-03-20
      • 2015-10-20
      • 2011-11-26
      • 2012-08-29
      • 2011-07-12
      • 1970-01-01
      • 2021-06-25
      • 2011-12-25
      • 1970-01-01
      相关资源
      最近更新 更多