NetBSD Problem Report #46248

From www@NetBSD.org  Fri Mar 23 01:08:19 2012
Return-Path: <www@NetBSD.org>
Received: from mail.netbsd.org (mail.netbsd.org [149.20.53.66])
	by www.NetBSD.org (Postfix) with ESMTP id BF54D63E3EB
	for <gnats-bugs@gnats.NetBSD.org>; Fri, 23 Mar 2012 01:08:19 +0000 (UTC)
Message-Id: <20120323010818.E7A0863B946@www.NetBSD.org>
Date: Fri, 23 Mar 2012 01:08:18 +0000 (UTC)
From: gnrp@komkon2.de
Reply-To: gnrp@komkon2.de
To: gnats-bugs@NetBSD.org
Subject: kevent won't return when kqueue is being closed
X-Send-Pr-Version: www-1.0

>Number:         46248
>Category:       kern
>Synopsis:       kevent won't return when kqueue is being closed
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    jdolecek
>State:          closed
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Fri Mar 23 01:10:01 +0000 2012
>Closed-Date:    Sun May 02 19:16:52 +0000 2021
>Last-Modified:  Sun May 02 19:20:01 +0000 2021
>Originator:     Julian Fagir
>Release:        6.0_BETA
>Organization:
>Environment:
NetBSD eselhitler 6.0_BETA NetBSD 6.0_BETA (ESELHITLER) #15: Fri Mar 16 12:21:49 CET 2012  gnrp@eselhitler:/home/ssd/netbsd-6.0/sys/arch/amd64/compile/obj/ESELHITLER amd64
NetBSD devrandom 6.0_BETA NetBSD 6.0_BETA (GENERIC) sparc64
>Description:
Apparently, FreeBSD and NetBSD handle kqueue'ing differently when the kqueue underneath a kevent(2) call is closed.

On FreeBSD, closing the kqueue just succeeds and kevent returns, or whatever, at least the close(2) call succeeds.
On NetBSD, the close won't return. If you have a pending kevent without timeout (i.e. last field set to NULL), you won't be able to shut that call down (at least not by this way).
>How-To-Repeat:
Save the attached program to `test.c`, and then compile and run with
`cc -lpthread test.c; time ./a.out`.
On NetBSD, this won't return until you stop it manually.
On FreeBSD, this will return after one second.


===test.c:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/event.h>
#include <sys/time.h>
#include <pthread.h>

static void *
closekq(void *kq)
{
        sleep(1);
        close(*(int *) kq);
        exit(0);
}

int
main(int argc, char *argv[])
{
        int kq, event;
        struct kevent kq_events;
        pthread_t thr;

        if ((kq = kqueue()) == -1)
                err(1, "kqueue");
        if (pthread_create(&thr, NULL, closekq, &kq))
                err(1, "pthread_create");
        event = kevent(kq, NULL, 0, &kq_events, 1, NULL);
        if (event == -1)
                err(1, "kevent");
        return 0;
}

>Fix:

>Release-Note:

>Audit-Trail:

Responsible-Changed-From-To: kern-bug-people->jdolecek
Responsible-Changed-By: jdolecek@NetBSD.org
Responsible-Changed-When: Sun, 24 Jan 2021 12:56:42 +0000
Responsible-Changed-Why:
Might look into this one, looks like useful to fix.


State-Changed-From-To: open->closed
State-Changed-By: jdolecek@NetBSD.org
State-Changed-When: Sun, 02 May 2021 19:16:52 +0000
State-Changed-Why:
Problem fixed.
It's unclear to me how FreeBSD managed to work - I was not able to find
any place in FreeBSD kernel which would wakeup the blocked kevent(2) call
when the descriptor is closed. Nevetheless, your test program now works
on NetBSD.


From: "Jaromir Dolecek" <jdolecek@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc: 
Subject: PR/46248 CVS commit: src/sys
Date: Sun, 2 May 2021 19:13:43 +0000

 Module Name:	src
 Committed By:	jdolecek
 Date:		Sun May  2 19:13:43 UTC 2021

 Modified Files:
 	src/sys/kern: kern_event.c
 	src/sys/sys: eventvar.h

 Log Message:
 implement fo_restart hook for kqueue descriptors, so that close(2)
 on the descriptor won't block indefinitely if other thread is currently
 blocked on the same kqueue in kevent(2)

 done similarily to pipes and sockets, i.e. using flag on the potentially
 shared kqueue structure hooked off file_t - this is somewhat suboptimal
 if the application dup(2)ped the descriptor, but this should be rare
 enough to not really matter

 usually this causes the kevent(2) to end up returning EBADF since
 on the syscall restart the descriptor is not there anymore; if
 dup(2)ped the kevent(2) call can continue successfully if the closed
 kqueue descriptor was other than the one used for the kevent(2)
 call

 PR kern/46248 by Julian Fagir


 To generate a diff of this commit:
 cvs rdiff -u -r1.117 -r1.118 src/sys/kern/kern_event.c
 cvs rdiff -u -r1.8 -r1.9 src/sys/sys/eventvar.h

 Please note that diffs are not public domain; they are subject to the
 copyright notices on the relevant files.

>Unformatted:

NetBSD Home
NetBSD PR Database Search

(Contact us) $NetBSD: query-full-pr,v 1.46 2020/01/03 16:35:01 leot Exp $
$NetBSD: gnats_config.sh,v 1.9 2014/08/02 14:16:04 spz Exp $
Copyright © 1994-2020 The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.