On Sun Sep 26, 2021 at 02:36:02PM +0200, Mark Kettenis wrote: > > Date: Fri, 24 Sep 2021 19:36:21 +0200 > > From: Rafael Sadowski <raf...@sizeofvoid.org> > > > > I'm trying to port the more KDE stuff so my question is from porter > > perspective. > > > > I need sigwaitinfo(2)/sigtimedwait(2) and I found both functions in > > lib/libc/gen/sigwait.c with the comment "need kernel to fill in more > > siginfo_t bits first". Is the comment still up to date? If no, is it > > possible to unlock the functions? > > Still true. These functions are somewhat underspecified by POSIX so > it isn't really obvious whatadditional bits need to be filled in. > Having examples of code that use these interfaces from ports could > help with that. >
One use-case from kscreenlocker-5.22.5/kcheckpass/kcheckpass.c Full code: https://github.com/KDE/kscreenlocker/blob/master/kcheckpass/kcheckpass.c It tries to handle SIGUSR1 and SIGUSR2. I think this can be solved in another way, so this is a bad example, isn't it? /* signal_info for sigwaitinfo() */ siginfo_t signalInfo; // now lets block on the fd for (;;) { conv_server(ConvPutReadyForAuthentication, 0); keventData = kevent(keventQueue, NULL, 0, keventEvent, 1, NULL); if (keventData == -1) { /* Let's figure this out in the future, shall we */ message("kevent() failed with %d\n", errno); return 1; } else if (keventData == 0) { /* Do we need to handle timeouts? */ message("kevent timeout\n"); continue; } // We know we got a SIGUSR1 or SIGUSR2, so fetch it via sigwaitinfo() // (otherwise, we could have used sigtimedwait() ) int signalReturn = sigwaitinfo(&signalMask, &signalInfo); if (signalReturn < 0) { if (errno == EINTR) { message("sigawaitinfo() interrupted by unblocked caught signal"); continue; } else if (errno == EAGAIN) { /* This should not happen, as kevent notified us about such a signal */ message("no signal of type USR1 or USR2 pending."); continue; } else { message("Unhandled error in sigwaitinfo()"); conv_server(ConvPutAuthError, 0); return 1; } } if (signalReturn == SIGUSR1) { if (signalInfo.si_pid != parentPid) { message("signal from wrong process\n"); continue; } /* Now do the fandango */ ret = Authenticate(method, username, conv_server); if (ret == AuthBad) { message("Authentication failure\n"); if (!nullpass) { openlog("kcheckpass", LOG_PID, LOG_AUTH); syslog(LOG_NOTICE, "Authentication failure for %s (invoked by uid %d)", username, uid); } } switch (ret) { case AuthOk: conv_server(ConvPutAuthSucceeded, 0); break; case AuthBad: conv_server(ConvPutAuthFailed, 0); break; case AuthError: conv_server(ConvPutAuthError, 0); break; case AuthAbort: conv_server(ConvPutAuthAbort, 0); default: break; } if (uid != geteuid()) { // we don't support multiple auth for setuid kcheckpass break; } } else if (signalReturn == SIGUSR2) { if (signalInfo.si_pid != parentPid) { message("signal from wrong process\n"); continue; } break; }