int el::lib_event_pipe_t::wait_event() { //!!!这里的日志不能使用线程打印,否则是死循环,继续调用日志事件!!! timeval time_out_val; time_out_val.tv_sec = 0; time_out_val.tv_usec = 100000;//100毫秒 fd_set fd_read_set; FD_ZERO(&fd_read_set); FD_SET(this->select_fd_max, &fd_read_set); int r = HANDLE_EINTR(::select(this->select_fd_max + 1, &fd_read_set, NULL, NULL, &time_out_val)); if (0 == r){//time out return 0; } if (ERR == r){ if (EBADF == errno){ //ALERT_LOG("[err_code:%d, err:%s]", errno, strerror(errno)); } return ERR; } if(FD_ISSET(this->select_fd_max, &fd_read_set)){ char sz[100]; int ret = (int)HANDLE_EINTR(::read(this->select_fd_max, sz, sizeof(sz))); return ret; } return 0; }
nsresult CreateTransport(base::ProcessId aProcIdOne, TransportDescriptor* aOne, TransportDescriptor* aTwo) { wstring id = IPC::Channel::GenerateVerifiedChannelID(std::wstring()); // Use MODE_SERVER to force creation of the socketpair Transport t(id, Transport::MODE_SERVER, nullptr); int fd1 = t.GetFileDescriptor(); int fd2, dontcare; t.GetClientFileDescriptorMapping(&fd2, &dontcare); if (fd1 < 0 || fd2 < 0) { return NS_ERROR_TRANSPORT_INIT; } // The Transport closes these fds when it goes out of scope, so we // dup them here fd1 = dup(fd1); fd2 = dup(fd2); if (fd1 < 0 || fd2 < 0) { HANDLE_EINTR(close(fd1)); HANDLE_EINTR(close(fd2)); return NS_ERROR_DUPLICATE_HANDLE; } aOne->mFd = base::FileDescriptor(fd1, true/*close after sending*/); aTwo->mFd = base::FileDescriptor(fd2, true/*close after sending*/); return NS_OK; }
static int OpenDeletedDirectory() { // We don't need this directory to persist between invocations of // the program (nor need it to be cleaned up if something goes wrong // here, because mkdtemp will choose a fresh name), so /tmp as // specified by FHS is adequate. char path[] = "/tmp/mozsandbox.XXXXXX"; if (!mkdtemp(path)) { SANDBOX_LOG_ERROR("mkdtemp: %s", strerror(errno)); return -1; } int fd = HANDLE_EINTR(open(path, O_RDONLY | O_DIRECTORY)); if (fd < 0) { SANDBOX_LOG_ERROR("open %s: %s", path, strerror(errno)); // Try to clean up. Shouldn't fail, but livable if it does. DebugOnly<bool> ok = HANDLE_EINTR(rmdir(path)) == 0; MOZ_ASSERT(ok); return -1; } if (HANDLE_EINTR(rmdir(path)) != 0) { SANDBOX_LOG_ERROR("rmdir %s: %s", path, strerror(errno)); AlwaysClose(fd); return -1; } return fd; }
// SBCELT_HelperMonitor implements a monitor thread that runs // when libsbcelt decides to use SBCELT_MODE_FUTEX. It is // response for determining whether the helper process has died, // and if that happens, restart it. static void *SBCELT_HelperMonitor(void *udata) { (void) udata; while (1) { uint64_t now = mtime(); uint64_t elapsed = now - lastdead; lastdead = now; // Throttle helper re-launches to around 1 per sec. if (elapsed < 1*USEC_PER_SEC) { usleep(1*USEC_PER_SEC); } debugf("restarted sbcelt-helper; %lu usec since last death", elapsed); pid_t child = fork(); if (child == -1) { // We're memory constrained. Wait and try again... usleep(5*USEC_PER_SEC); continue; } else if (child == 0) { // For SBCELT_SANDBOX_SECCOMP_BPF, it shouldn't matter // whether the child inherits any file descriptors, since // the only useful system call the process can make is futex(2). // // However, if we're running in Futex mode without a sandbox, // closing the file descriptors is indeed a good idea, which // is why we do it unconditionally below. (void) HANDLE_EINTR(close(0)); (void) HANDLE_EINTR(close(1)); #ifndef DEBUG xclosefrom(2); #else xclosefrom(3); #endif char *const argv[] = { SBCELT_HelperBinary(), NULL, }; execv(argv[0], argv); _exit(100); } int status; int retval = HANDLE_EINTR(waitpid(child, &status, 0)); if (retval == child) { if (WIFEXITED(status)) { debugf("sbcelt-helper died with exit status: %i", WEXITSTATUS(status)); } else if (WIFSIGNALED(status)) { debugf("sbcelt-helper died with signal: %i", WTERMSIG(status)); } } else if (retval == -1 && errno == EINVAL) { fprintf(stderr, "libsbcelt: waitpid() failed with EINVAL; internal error!\n"); fflush(stderr); exit(1); } } }
static int compare_timezone_to_localtime( ScanDataRec* scan, const char* path ) { struct stat st; int fd1, fd2, result = 0; D( "%s: comparing %s:", __FUNCTION__, path ); if ( stat( path, &st ) < 0 ) { D( " can't stat: %s\n", strerror(errno) ); return 0; } if ( st.st_size != scan->localtime_st.st_size ) { D( " size mistmatch (%zd != %zd)\n", (size_t)st.st_size, (size_t)scan->localtime_st.st_size ); return 0; } fd1 = open( scan->localtime, O_RDONLY ); if (fd1 < 0) { D(" can't open %s: %s\n", scan->localtime, strerror(errno) ); return 0; } fd2 = open( path, O_RDONLY ); if (fd2 < 0) { D(" can't open %s: %s\n", path, strerror(errno) ); close(fd1); return 0; } do { off_t nn; for (nn = 0; nn < st.st_size; nn++) { char temp[2]; int ret; ret = HANDLE_EINTR(read(fd1, &temp[0], 1)); if (ret < 0) break; ret = HANDLE_EINTR(read(fd2, &temp[1], 1)); if (ret < 0) break; if (temp[0] != temp[1]) break; } result = (nn == st.st_size); } while (0); D( result ? " MATCH\n" : "no match\n" ); close(fd2); close(fd1); return result; }
void connector(attendant__pipe_t in, attendant__pipe_t out) { const char *pipe = "pipe\n"; int err; HANDLE_EINTR(write(in, pipe, strlen(pipe)), err); ok(err != -1, "request pipe"); HANDLE_EINTR(read(out, fifo, sizeof(fifo)), err); fifo[strlen(fifo) - 1] = '\0'; ok(err != -1, "get pipe # %s", fifo); }
static int SBCELT_RWHelper() { while (1) { // Wait for the lib to signal us. if (HANDLE_EINTR(read(0, &workpage->pingpong, 1)) == -1) { return -2; } SBCELT_DecodeSingleFrame(); if (HANDLE_EINTR(write(1, &workpage->pingpong, 1)) == -1) { return -3; } } }
// Block until child_pid exits, then exit. Try to preserve the exit code. static void WaitForChildAndExit(pid_t child_pid) { int exit_code = -1; siginfo_t reaped_child_info; // Don't "Core" on SIGABRT. SIGABRT is sent by the Chrome OS session manager // when things are hanging. // Here, the current process is going to waitid() and _exit(), so there is no // point in generating a crash report. The child process is the one // blocking us. if (signal(SIGABRT, ExitWithErrorSignalHandler) == SIG_ERR) { FatalError("Failed to change signal handler"); } int wait_ret = HANDLE_EINTR(waitid(P_PID, child_pid, &reaped_child_info, WEXITED)); if (!wait_ret && reaped_child_info.si_pid == child_pid) { if (reaped_child_info.si_code == CLD_EXITED) { exit_code = reaped_child_info.si_status; } else { // Exit with code 0 if the child got signaled. exit_code = 0; } } _exit(exit_code); }
/** socket_send_to : 'socket -> buf:string -> pos:int -> length:int -> addr:{host:'int32,port:int} -> int <doc> Send data from an unconnected UDP socket to the given address. </doc> **/ static value socket_send_to( value o, value data, value pos, value len, value vaddr ) { int p,l,dlen; value host, port; struct sockaddr_in addr; val_check_kind(o,k_socket); val_check(data,string); val_check(pos,int); val_check(len,int); val_check(vaddr,object); host = val_field(vaddr, f_host); port = val_field(vaddr, f_port); val_check(host,int32); val_check(port,int); p = val_int(pos); l = val_int(len); dlen = val_strlen(data); memset(&addr,0,sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(val_int(port)); *(int*)&addr.sin_addr.s_addr = val_int32(host); if( p < 0 || l < 0 || p > dlen || p + l > dlen ) neko_error(); POSIX_LABEL(send_again); dlen = sendto(val_sock(o), val_string(data) + p , l, MSG_NOSIGNAL, (struct sockaddr*)&addr, sizeof(addr)); if( dlen == SOCKET_ERROR ) { HANDLE_EINTR(send_again); return block_error(); } return alloc_int(dlen); }
bool app_launcher::get_output(int pipe, vogl::dynamic_string &output, size_t max_output) { if (pipe != -1) { if (max_output <= 0) return true; for(;;) { char buf[4096]; size_t nbytes = max_output; if (nbytes >= sizeof(buf)) nbytes = sizeof(buf); // Try to read in nbytes. read returns 0:end of file, -1:error. ssize_t length = HANDLE_EINTR(read(pipe, buf, nbytes)); if (length < 0) return false; max_output -= length; output.append(buf, (uint)length); if ((length != (ssize_t)nbytes) || (max_output <= 0)) return true; } } return false; }
// SBCELT_CheckSeccomp checks for kernel support for // SECCOMP. // // On success, the function returns a valid sandbox // mode (see SBCELT_SANDBOX_*). // // On failure, the function returns // -1 if the helper process did not execute correctly. // -2 if the fork system call failed. This signals that the // host system is running low on memory. This is a // recoverable error, and in our case we should simply // wait a bit and try again. static int SBCELT_CheckSeccomp() { int status, err; pid_t child; child = fork(); if (child == -1) { return -2; } else if (child == 0) { char *const argv[] = { SBCELT_HelperBinary(), "detect", NULL, }; execv(argv[0], argv); _exit(100); } if (HANDLE_EINTR(waitpid(child, &status, 0)) == -1) { return -1; } if (!WIFEXITED(status)) { return -1; } int code = WEXITSTATUS(status); if (!SBCELT_SANDBOX_VALID(code)) { return -1; } return code; }
/** socket_close : 'socket -> void <doc>Close a socket. Any subsequent operation on this socket will fail</doc> **/ static value socket_close( value o ) { POSIX_LABEL(close_again); if( closesocket(val_sock(o)) ) { HANDLE_EINTR(close_again); } return alloc_bool(true); }
/** socket_select : read : 'socket array -> write : 'socket array -> others : 'socket array -> timeout:number? -> 'socket array array <doc>Perform the [select] operation. Timeout is in seconds or [null] if infinite</doc> **/ static value socket_select( value rs, value ws, value es, value timeout ) { struct timeval tval; struct timeval *tt; SOCKET n = 0; fd_set rx, wx, ex; fd_set *ra, *wa, *ea; value r; POSIX_LABEL(select_again); ra = make_socket_array(rs,val_array_size(rs),&rx,&n); wa = make_socket_array(ws,val_array_size(ws),&wx,&n); ea = make_socket_array(es,val_array_size(es),&ex,&n); if( ra == &INVALID || wa == &INVALID || ea == &INVALID ) neko_error(); if( val_is_null(timeout) ) tt = NULL; else { val_check(timeout,number); tt = &tval; init_timeval(val_number(timeout),tt); } if( select((int)(n+1),ra,wa,ea,tt) == SOCKET_ERROR ) { HANDLE_EINTR(select_again); neko_error(); } r = alloc_array(3); val_array_ptr(r)[0] = make_array_result(rs,ra); val_array_ptr(r)[1] = make_array_result(ws,wa); val_array_ptr(r)[2] = make_array_result(es,ea); return r; }
/** socket_recv : 'socket -> buf:string -> pos:int -> len:int -> int <doc>Read up to [len] bytes from [buf] starting at [pos] from a connected socket. Return the number of bytes readed.</doc> **/ static value socket_recv( value o, value data, value pos, value len ) { int p,l,dlen,ret; int retry = 0; val_check_kind(o,k_socket); val_check(data,string); val_check(pos,int); val_check(len,int); p = val_int(pos); l = val_int(len); dlen = val_strlen(data); if( p < 0 || l < 0 || p > dlen || p + l > dlen ) neko_error(); POSIX_LABEL(recv_again); if( retry++ > NRETRYS ) { sock_tmp t; t.sock = val_sock(o); t.buf = val_string(data) + p; t.size = l; neko_thread_blocking(tmp_recv,&t); ret = t.ret; } else ret = recv(val_sock(o), val_string(data) + p , l, MSG_NOSIGNAL); if( ret == SOCKET_ERROR ) { HANDLE_EINTR(recv_again); return block_error(); } return alloc_int(ret); }
static value socket_recv_from( value o, value dataBuf, value pos, value len, value addr ) { int p,l,ret; int retry = 0; struct sockaddr_in saddr; SockLen slen = sizeof(saddr); val_check_kind(o,k_socket); val_check(dataBuf,buffer); buffer buf = val_to_buffer(dataBuf); char *data = buffer_data(buf); int dlen = buffer_size(buf); val_check(pos,int); val_check(len,int); val_check(addr,object); p = val_int(pos); l = val_int(len); if( p < 0 || l < 0 || p > dlen || p + l > dlen ) neko_error(); SOCKET sock = val_sock(o); gc_enter_blocking(); POSIX_LABEL(recv_from_again); if( retry++ > NRETRYS ) { ret = recv(sock,data+p,l,MSG_NOSIGNAL); } else ret = recvfrom(sock, data + p , l, MSG_NOSIGNAL, (struct sockaddr*)&saddr, &slen); if( ret == SOCKET_ERROR ) { HANDLE_EINTR(recv_from_again); return block_error(); } gc_exit_blocking(); alloc_field(addr,f_host,alloc_int32(*(int*)&saddr.sin_addr)); alloc_field(addr,f_port,alloc_int(ntohs(saddr.sin_port))); return alloc_int(ret); }
/** socket_send_to : 'socket -> buf:string -> pos:int -> length:int -> addr:{host:'int32,port:int} -> int <doc> Send data from an unconnected UDP socket to the given address. </doc> **/ static value socket_send_to( value o, value dataBuf, value pos, value len, value vaddr ) { int p,l; value host, port; struct sockaddr_in addr; val_check_kind(o,k_socket); buffer buf = val_to_buffer(dataBuf); const char *cdata = buffer_data(buf); int dlen = buffer_size(buf); val_check(pos,int); val_check(len,int); val_check(vaddr,object); host = val_field(vaddr, f_host); port = val_field(vaddr, f_port); val_check(host,int); val_check(port,int); p = val_int(pos); l = val_int(len); memset(&addr,0,sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(val_int(port)); *(int*)&addr.sin_addr.s_addr = val_int(host); if( p < 0 || l < 0 || p > dlen || p + l > dlen ) neko_error(); SOCKET sock = val_sock(o); gc_enter_blocking(); POSIX_LABEL(send_again); dlen = sendto(sock, cdata + p , l, MSG_NOSIGNAL, (struct sockaddr*)&addr, sizeof(addr)); if( dlen == SOCKET_ERROR ) { HANDLE_EINTR(send_again); return block_error(); } gc_exit_blocking(); return alloc_int(dlen); }
/* * Asynchronous I/O callback launched when framebuffer notifications are ready * to be read. * Param: * opaque - FrameBufferImpl instance. */ static void _fbUpdatesImpl_io_callback(void* opaque, int fd, unsigned events) { FrameBufferImpl* fbi = opaque; int ret; // Read updates while they are immediately available. for (;;) { // Read next chunk of data. ret = HANDLE_EINTR( socket_recv(fbi->sock, fbi->reader_buffer + fbi->reader_offset, fbi->reader_bytes - fbi->reader_offset)); if (ret < 0 && (errno == EWOULDBLOCK || errno == EAGAIN)) { // Chunk is not avalable at this point. Come back later. return; } if (ret <= 0) { /* disconnection ! */ derror("Unable to receive framebuffer data: %s\n", ret < 0 ? strerror(errno), "unexpected disconnection"); fbUpdatesImpl_destroy(); return; } fbi->reader_offset += ret; if (fbi->reader_offset != fbi->reader_bytes) { // There are still some data left in the pipe. continue; } // All expected data has been read. Time to change the state. if (fbi->fb_state == EXPECTS_HEADER) { // Update header has been read. Prepare for the pixels. fbi->fb_state = EXPECTS_PIXELS; fbi->reader_offset = 0; fbi->reader_bytes = fbi->update_header.w * fbi->update_header.h * (fbi->bits_per_pixel / 8); fbi->reader_buffer = malloc(fbi->reader_bytes); if (fbi->reader_buffer == NULL) { APANIC("Unable to allocate memory for framebuffer update\n"); } } else { // Pixels have been read. Prepare for the header. uint8_t* pixels = fbi->reader_buffer; fbi->fb_state = EXPECTS_HEADER; fbi->reader_offset = 0; fbi->reader_bytes = sizeof(FBUpdateMessage); fbi->reader_buffer = (uint8_t*)&fbi->update_header; // Perform the update. Note that pixels buffer must be freed there. _update_rect(fbi->fb, fbi->update_header.x, fbi->update_header.y, fbi->update_header.w, fbi->update_header.h, fbi->bits_per_pixel, pixels); } }
static bool CanCreateUserNamespace() { // Unfortunately, the only way to verify that this process can // create a new user namespace is to actually create one; because // this process's namespaces shouldn't be side-effected (yet), it's // necessary to clone (and collect) a child process. See also // Chromium's sandbox::Credentials::SupportsNewUserNS. // // This is somewhat more expensive than the other tests, so it's // cached in the environment to prevent child processes from having // to re-run the test. // // This is run at static initializer time, while single-threaded, so // locking isn't needed to access the environment. static const char kCacheEnvName[] = "MOZ_ASSUME_USER_NS"; const char* cached = getenv(kCacheEnvName); if (cached) { return cached[0] > '0'; } // Valgrind might allow the clone, but doesn't know what to do with // unshare. Check for that by unsharing nothing. (Valgrind will // probably need sandboxing disabled entirely, but no need to break // things worse than strictly necessary.) if (syscall(__NR_unshare, 0) != 0) { #ifdef MOZ_VALGRIND MOZ_ASSERT(errno == ENOSYS); #else // If something else can cause that call to fail, we's like to know // about it; the right way to handle it might not be the same. MOZ_ASSERT(false); #endif return false; } pid_t pid = syscall(__NR_clone, SIGCHLD | CLONE_NEWUSER, nullptr, nullptr, nullptr, nullptr); if (pid == 0) { // In the child. Do as little as possible. _exit(0); } if (pid == -1) { // Failure. MOZ_ASSERT(errno == EINVAL || // unsupported errno == EPERM || // root-only, or we're already chrooted errno == EUSERS); // already at user namespace nesting limit setenv(kCacheEnvName, "0", 1); return false; } // Otherwise, in the parent and successful. bool waitpid_ok = HANDLE_EINTR(waitpid(pid, nullptr, 0)) == pid; MOZ_ASSERT(waitpid_ok); if (!waitpid_ok) { return false; } setenv(kCacheEnvName, "1", 1); return true; }
int I2C::i2c_read(uint8_t *data, int length, int &read_length) { const int res = HANDLE_EINTR(::read(m_fd, data, length)); if (res < 0) return errno; read_length = res; return 0; }
int I2C::i2c_set_slave_address(int address) { if (m_fd == -1) return EBADF; const int res = HANDLE_EINTR(::ioctl(m_fd, I2C_SLAVE_FORCE, address)); return res ? errno : 0; }
static int do_close( int fd ) { POSIX_LABEL(close_again); if( close(fd) != 0 ) { HANDLE_EINTR(close_again); return 1; } return 0; }
void I2C::shutdown() { logger(LOG_INFO, "i2c shutting down"); if (m_fd != -1) { HANDLE_EINTR(::close(m_fd)); m_fd = -1; } }
/** socket_poll_events : 'poll -> timeout:float -> void <doc> Update the read/write flags arrays that were created with [socket_poll_prepare]. </doc> **/ static value socket_poll_events( value pdata, value timeout ) { polldata *p; # ifdef NEKO_WINDOWS unsigned int i; int k = 0; struct timeval t; val_check_kind(pdata,k_poll); p = val_poll(pdata); memcpy(p->outr,p->fdr,FDSIZE(p->fdr->fd_count)); memcpy(p->outw,p->fdw,FDSIZE(p->fdw->fd_count)); val_check(timeout,number); init_timeval(val_number(timeout),&t); gc_enter_blocking(); if( p->fdr->fd_count + p->fdw->fd_count != 0 && select(0,p->outr,p->outw,NULL,&t) == SOCKET_ERROR ) { gc_exit_blocking(); return alloc_null(); } gc_exit_blocking(); k = 0; for(i=0;i<p->fdr->fd_count;i++) if( FD_ISSET(p->fdr->fd_array[i],p->outr) ) val_array_set_i(p->ridx,k++,alloc_int(i)); val_array_set_i(p->ridx,k,alloc_int(-1)); k = 0; for(i=0;i<p->fdw->fd_count;i++) if( FD_ISSET(p->fdw->fd_array[i],p->outw) ) val_array_set_i(p->widx,k++, alloc_int(i)); val_array_set_i(p->widx,k,alloc_int(-1)); #else int i,k; int tot; val_check_kind(pdata,k_poll); val_check(timeout,number); p = val_poll(pdata); tot = p->rcount + p->wcount; gc_enter_blocking(); POSIX_LABEL(poll_events_again); if( poll(p->fds,tot,(int)(val_number(timeout) * 1000)) < 0 ) { HANDLE_EINTR(poll_events_again); gc_exit_blocking(); return alloc_null(); } gc_exit_blocking(); k = 0; for(i=0;i<p->rcount;i++) if( p->fds[i].revents & (POLLIN|POLLHUP) ) val_array_set_i(p->ridx,k++,alloc_int(i)); val_array_set_i(p->ridx,k, alloc_int(-1)); k = 0; for(;i<tot;i++) if( p->fds[i].revents & (POLLOUT|POLLHUP) ) val_array_set_i(p->widx,k++, alloc_int(i - p->rcount)); val_array_set_i(p->widx,k, alloc_int(-1)); #endif return val_null; }
int el::lib_event_pipe_t::notify_event() { char f; int r = (int)HANDLE_EINTR(::write(this->event_pipe.write_fd(), &f, 1)); if (-1 == r){ ALERT_LOG("[err_code:%d, err:%s]", errno, strerror(errno)); } return r; }
/** socket_close : 'socket -> void <doc>Close a socket. Any subsequent operation on this socket will fail</doc> **/ static value socket_close( value o ) { val_check_kind(o,k_socket); POSIX_LABEL(close_again); if( closesocket(val_sock(o)) ) { HANDLE_EINTR(close_again); } val_kind(o) = NULL; return val_true; }
/* Reads 'nbyte' bytes from 'fd' into 'buf', retrying on interrupts. * Exit()s if the read fails for any other reason. */ static int read_or_die(int fd, void *buf, size_t nbyte) { int ret = HANDLE_EINTR(read(fd, buf, nbyte)); if (ret < 0) { derror("read failed: %s", strerror(errno)); exit(1); } return ret; }
int i2c_smbus_access(int fh, uint8_t read_write, uint8_t command, int size, union i2c_smbus_data *data) { i2c_smbus_ioctl_data args; args.read_write = read_write; args.command = command; args.size = size; args.data = data; return HANDLE_EINTR(::ioctl(fh, I2C_SMBUS, &args)); }
// static void MessagePumpLibevent::OnWakeup(int socket, short flags, void* context) { MessagePumpLibevent* that = static_cast<MessagePumpLibevent*>(context); assert(that->wakeup_pipe_out_ == socket); // Remove and discard the wakeup byte. char buf; long nread = HANDLE_EINTR(read(socket, &buf, 1)); assert(nread == 1); that->processed_io_events_ = true; // Tell libevent to break out of inner loop. event_base_loopbreak(that->event_base_); }
static value ssl_handshake( value ssl ) { int r; val_check_kind(ssl,k_ssl); POSIX_LABEL(handshake_again); r = mbedtls_ssl_handshake( val_ssl(ssl) ); if( r == SOCKET_ERROR ) { HANDLE_EINTR(handshake_again); return block_error(); }else if( r != 0 ) return ssl_error(r); return val_true; }
/** socket_accept : 'socket -> 'socket <doc>Accept an incoming connection request</doc> **/ static value socket_accept( value o ) { struct sockaddr_in addr; unsigned int addrlen = sizeof(addr); SOCKET s; val_check_kind(o,k_socket); POSIX_LABEL(accept_again); s = accept(val_sock(o),(struct sockaddr*)&addr,&addrlen); if( s == INVALID_SOCKET ) { HANDLE_EINTR(accept_again); return block_error(); } return alloc_abstract(k_socket,(value)(int_val)s); }