exaloop/codon

Don't work Ptr epoll_event in epoll_wait

flykker opened this issue · 3 comments

I develop epoll linux on codon

Don't work epoll_wait

class epoll_data:
    ptr: Ptr[byte]
    fd: i32
    u32: u32
    u64: u64
    
    def __init__(self):
        pass
    
    def __repr__(self) -> str:
        return f'[ptr={self.ptr},fd={self.fd},u32={self.u32},u64={self.u64}]'


class epoll_event:
    events: u32
    data: epoll_data

    def __init__(self):
        self.events = u32(0)
        self.data = epoll_data()
    
    def __repr__(self) -> str:
        return f'[events={self.events},data={self.data}]'

from C import epoll_create(i32) -> i32
from C import epoll_ctl(i32, i32, i32, epoll_event) -> i32
from C import epoll_wait(i32, Ptr[epoll_event], i32, i32) -> i32

EPOLLIN = u32(001)
EPOLL_CTL_ADD = i32(1)


host = '127.0.0.1' # Symbolic name meaning all available interfaces
port = 12346       # Arbitrary non-privileged port

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host, port))

print(host, port)
s.listen(1)

events = Array[epoll_event](256)
print(events.ptr)


ev = epoll_event()
ev.events = EPOLLIN
ev.data.fd = s.__sock

print(ev)

epollfd = epoll_create(i32(256))

epoll_ctl(epollfd, EPOLL_CTL_ADD, s.__sock, ev)

while True:
    new_events = epoll_wait(epollfd, events.ptr, i32(256), i32(-1))

    if int(new_events) > 0:
        print(int(new_events))
        
        events[0].events = EPOLLIN
        sys.exit(1)

When I get events[0] i get Segmention fault C

But in strace I see what epoll_wait

socket(AF_INET, SOCK_STREAM, IPPROTO_IP) = 3
bind(3, {sa_family=AF_INET, sin_port=htons(12346), sin_addr=inet_addr("127.0.0.1")}, 16) = 0
newfstatat(1, "", {st_mode=S_IFCHR|0620, st_rdev=makedev(0x88, 0x2), ...}, AT_EMPTY_PATH) = 0
write(1, "127.0.0.1 12346\n", 16127.0.0.1 12346
)       = 16
listen(3, 1)                            = 0
write(1, "0x7f8e36b85000\n", 150x7f8e36b85000
)        = 15
write(1, "[events=1,data=[ptr=0x0,fd=3,u32"..., 43[events=1,data=[ptr=0x0,fd=3,u32=0,u64=0]]
) = 43
epoll_create(256)                       = 4
epoll_ctl(4, EPOLL_CTL_ADD, 3, {events=EPOLLIN, data={u32=0, u64=3942918103876239360}}) = 0
epoll_wait(4, [{events=EPOLLIN, data={u32=0, u64=3942918103876239360}}], 256, -1) = 1
write(1, "1\n", 21
)                      = 2
--- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_MAPERR, si_addr=0x1} ---
+++ killed by SIGSEGV (core dumped) +++
Segmentation fault (core dumped)

I see what set array [{events=EPOLLIN, data={u32=0, u64=3942918103876239360}}] epoll_event but
in code events[0] is epmty

Please help !

I victory my problem

And it's result code

import socket
import sys
import os

class epoll_data:
    ptr: Ptr[byte]
    fd: i32
    u32: u32
    u64: u64
   
    def __repr__(self) -> str:
        return f'[ptr={self.ptr},fd={self.fd},u32={self.u32},u64={self.u64}]'

@tuple
class epoll_event:
    events: u32
    data: epoll_data

    def __new__(_events: u32, _data: epoll_data):
         return epoll_event(_events, _data)
    
    def __repr__(self) -> str:
        return f'[events={self.events},data={self.data}]'

from C import epoll_create(i32) -> i32
from C import epoll_ctl(i32, i32, i32, Ptr[byte]) -> i32
from C import epoll_wait(i32, Ptr[byte], i32, i32) -> i32

EPOLLIN = u32(0x001)
EPOLLET = u32(int(1u) << 31)

EPOLL_CTL_ADD = i32(1)
EPOLL_CTL_DEL = i32(2)
EPOLL_CTL_MOD = i32(3)

host = '127.0.0.1' # Symbolic name meaning all available interfaces
port = 8001       # Arbitrary non-privileged port

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket.setnonblocking(s.__sock);

s.bind((host, port))

s.listen(1)
print(host, port)

wait_events = __array__[epoll_event](256)

ev = epoll_event(EPOLLIN)

ev.data.fd = s.__sock

print(ev)

epollfd = epoll_create(i32(256))

epoll_ctl(epollfd, EPOLL_CTL_ADD, s.__sock, __ptr__(ev).as_byte())


while True:
    new_events = epoll_wait(epollfd, wait_events.ptr.as_byte(), i32(256), i32(-1))

    print(int(new_events))

    if int(new_events) == -1:
        break

    for i in range(int(new_events)):  
        print(i)

        event = wait_events[i]

        print(f'Event: {event}')
                
        if event.data.fd == s.__sock:
            sock_conn, sock_addr = s.accept()
            socket.setnonblocking(sock_conn.__sock);

            print('Connected by: ', sock_addr)

            ev2 = epoll_event(EPOLLIN | EPOLLET)
            ev2.data.fd = sock_conn.__sock
            
            epoll_ctl(epollfd, EPOLL_CTL_ADD, sock_conn.__sock, __ptr__(ev2).as_byte())
        else:
            newsockfd = event.data.fd

            data = socket.recv(newsockfd, 1024)
            
            print("Client says: " + data)

            if not data:
                break
            else:
                #shutdown(newsockfd, SHUT_RDWR)
                socket.sendall(newsockfd, "HTTP/1.1 200 OK\nServer: Z-Server\nContent-type: text/html\n\n<html><body>Z-Server</body></html>")
                epoll_ctl(epollfd, EPOLL_CTL_DEL, newsockfd, Ptr[byte](0))
                socket.close(newsockfd)

But when run and build sometime not working and
in it place code

event = wait_events[i]
print(f'Event: {event}')

Get sometimes Segmentation Fault .... Very very strange

Please help ! Codon is the Super !

  • and when run with

codon run -release http_server.codon

All times Segmentation Fault

event = wait_events[i]
print(f'Event: {event}')

This is definitely a bug—thank you for the report!

Also, you should initialize ptr here:

    def __init__(self):
        pass

Otherwise it will get garbage value and might cause segfault.