Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement sigtimedwait for use by suckless init #1320

Open
wants to merge 48 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
a219223
Add /sbin/init based on suckless sinit.
cahirwpz Jul 26, 2022
7286e68
First check tests to run then run init.
cahirwpz Jul 26, 2022
e07f7c1
Merge branch 'master' into suckless-sinit
cahirwpz Oct 14, 2022
6f5ad93
wip
korbiniak Nov 9, 2022
3d15ce3
[WIP] do_sigtimedwait
korbiniak Nov 10, 2022
1e3744d
Merge branch 'master' into suckless-sinit
cahirwpz Nov 10, 2022
1ce829f
[WIP] Sigtimedwait finished, first test
korbiniak Dec 18, 2022
000d730
Add /sbin/init based on suckless sinit.
cahirwpz Jul 26, 2022
2d7ca28
First check tests to run then run init.
cahirwpz Jul 26, 2022
b386909
wip
korbiniak Nov 9, 2022
fb3eaa3
[WIP] do_sigtimedwait
korbiniak Nov 10, 2022
e41929e
[WIP] Sigtimedwait finished, first test
korbiniak Dec 18, 2022
7abe9f9
Merge branch 'master' into suckless-sinit
cahirwpz Dec 18, 2022
35a1ecc
Fixes after merge.
cahirwpz Dec 18, 2022
c486015
Revert changes to the build & test infrastructure.
cahirwpz Dec 18, 2022
bc5288f
Merge branch 'suckless-sinit' of github.com:cahirwpz/mimiker into suc…
korbiniak Dec 30, 2022
7b0199c
Sigtimedwait finished
korbiniak Dec 30, 2022
239ca0e
format
korbiniak Dec 30, 2022
da05dd4
Fixed llvm version
korbiniak Dec 30, 2022
54b38ef
format
korbiniak Dec 30, 2022
1994eb2
Fixed launch changes
korbiniak Dec 30, 2022
b301a1c
Fixed race in timeout test
korbiniak Jan 1, 2023
ac3908b
Format.
korbiniak Jan 1, 2023
51bbe9f
Lowered the timeout in signal_sigtimedwait_timeout test.
korbiniak Jan 1, 2023
cbf8c25
Lower the timeout even more.
korbiniak Jan 1, 2023
29c302b
Merge branch 'master' into suckless-sinit
cahirwpz Jan 3, 2023
e597ef4
Remove sbin/init as it's a part of contrib directory
cahirwpz Jan 3, 2023
eff8b00
Merge branch 'master' into suckless-sinit
korbiniak Jan 12, 2023
76ca8f1
Use new utest interface for sigtimedwait tests.
korbiniak Jan 12, 2023
c576c73
Use new utest util macros.
korbiniak Jan 12, 2023
db00050
Check only for waited signals in the pending mask.
korbiniak Jan 12, 2023
4088dd6
Handle bad timeout format.
korbiniak Jan 13, 2023
cdfc493
Remove printf's from test, assert on all syscalls.
korbiniak Jan 13, 2023
f7977d5
Use utest_spawn and utest_child_exited
korbiniak Jan 14, 2023
97d0591
Clean up do_sigtimedwait
korbiniak Jan 19, 2023
f9014c9
Refactor tests
korbiniak Jan 19, 2023
a5fb873
Tidy up
korbiniak Jan 20, 2023
0c30ce6
Merge branch 'master' into suckless-sinit
cahirwpz Jun 8, 2023
86c4f14
Merge branch 'master' into suckless-sinit
cahirwpz Jun 14, 2023
3c7670d
Address some long standing remarks (pt. 1)
cahirwpz Jun 14, 2023
4b8edb8
Address some long lasting remarks (pt. 2)
cahirwpz Jun 14, 2023
65da74e
Address some long lasting remarks (pt. 3)
cahirwpz Jun 15, 2023
b4caf4b
Merge branch 'master' into suckless-sinit
cahirwpz Jul 26, 2023
d1df936
Fix tests.
cahirwpz Jul 28, 2023
59d3c58
Merge branch 'master' into suckless-sinit
cahirwpz Jul 28, 2023
c3c4abd
Merge branch 'master' into suckless-sinit
cahirwpz Jul 28, 2023
cfab58a
Merge branch 'master' into suckless-sinit
cahirwpz Aug 1, 2023
78e955b
Merge branch 'master' into suckless-sinit
cahirwpz Aug 1, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
TOPDIR = $(CURDIR)

# Directories which require calling make recursively
SUBDIR = sys lib bin usr.bin etc include contrib
SUBDIR = sys lib bin usr.bin sbin etc include contrib

all: install

Expand Down
2 changes: 2 additions & 0 deletions bin/utest/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ int main(int argc, char **argv) {
CHECKRUN_TEST(signal_cont_masked);
CHECKRUN_TEST(signal_mask);
CHECKRUN_TEST(signal_mask_nonmaskable);
CHECKRUN_TEST(signal_sigtimedwait);
CHECKRUN_TEST(signal_sigtimedwait_timeout);
CHECKRUN_TEST(signal_sigsuspend);
CHECKRUN_TEST(signal_sigsuspend_stop);
CHECKRUN_TEST(signal_handler_mask);
Expand Down
85 changes: 85 additions & 0 deletions bin/utest/signal.c
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
#include <assert.h>
#include <signal.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <sched.h>
#include <sys/wait.h>

#include "sys/errno.h"
#include "sys/signal.h"
#include "utest.h"
#include "util.h"

Expand Down Expand Up @@ -287,6 +290,88 @@ int test_signal_sigsuspend(void) {
return 0;
}

/* ======= signal_sigtimedwait ======= */
int test_signal_sigtimedwait(void) {
pid_t ppid = getpid();
signal(SIGCONT, sigcont_handler);
sigset_t set, current, waitset;
__sigemptyset(&set);
__sigaddset(&set, SIGUSR1);
__sigaddset(&set, SIGCONT);
cahirwpz marked this conversation as resolved.
Show resolved Hide resolved
assert(sigprocmask(SIG_SETMASK, &set, NULL) == 0);
cahirwpz marked this conversation as resolved.
Show resolved Hide resolved
pid_t cpid = fork();
if (cpid == 0) {
// for (int i = 0; i < 10; i++) {
cahirwpz marked this conversation as resolved.
Show resolved Hide resolved
// kill(ppid, SIGCONT);
// }
// sched_yield();
kill(ppid, SIGUSR1);
return 0;
}

printf("Calling sigtimedwait()...\n");
siginfo_t info;
__sigemptyset(&waitset);
__sigaddset(&waitset, SIGUSR1);
assert(sigtimedwait(&waitset, &info, NULL) == SIGUSR1);
cahirwpz marked this conversation as resolved.
Show resolved Hide resolved
assert(info.si_signo == SIGUSR1);
sigprocmask(SIG_BLOCK, NULL, &current);
assert(__sigsetequal(&set, &current));

printf("Waiting for child...\n");
int status;
wait(&status);
assert(WIFEXITED(status));
assert(WEXITSTATUS(status) == 0);
return 0;
}

/* ======= signal_sigtimedwait_timeout ======= */
static int sigusr2_handled = 0;

void sigtimedwait_timeout_sigusr2_handler(int signo) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why don't you name it sigusr2_handler?

Copy link
Collaborator

@korbiniak korbiniak Jan 19, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This way I know that some particular test will be the only user of this function.
Suppose someone in the future would like to use the sigusr2 for testing, then they'd need to create a new function, how would they name it then? They could reuse this function, but I advise against that. If one would like to change the behavior of the handler for some particular test they'd need to create a new function and give it some other name anyway.

EDIT: Maybe it's an overkill, I don't know, wdyt?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggested it because I see that in other signal tests we name functions that looks like that always in the same way. These functions are used in multiple tests and I think there is nothing wrong in that (they are used identically so why we would like to duplicate code?).

If you would like to add some functionality to such function then it is a reason to make function with unique name (and leave the old one unchanged because we expect some specific behavior from it).

@cahirwpz @pwit81 I think that we can think about making such function a standard. They are used pretty often and maybe we don't have to invent new functions for just handling one signal for every written test?

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@franciscozdo @korbiniak It's definitely a good idea to factor it out.

I'd do it by extending our current utest.h interface by adding:

  • void signal_count(int signo) - registers a generic handler for signo signal,
  • int signal_counter(int signo) - returns a number of times signal signo was delivered.

If you have a better idea how to name those functions then feel free to do so.

sigusr2_handled = 1;
}

int test_signal_sigtimedwait_timeout(void) {
pid_t ppid = getpid();
signal(SIGCONT, sigcont_handler);
signal(SIGUSR2, sigtimedwait_timeout_sigusr2_handler);
sigset_t set, waitset;
__sigemptyset(&set);
__sigaddset(&set, SIGUSR1);
assert(sigprocmask(SIG_SETMASK, &set, NULL) == 0);
pid_t cpid = fork();
if (cpid == 0) {
while (!sigusr2_handled) {
kill(ppid, SIGCONT);
}
return 0;
}

printf("Calling sigtimedwait()...\n");
siginfo_t info;
__sigemptyset(&waitset);
__sigaddset(&waitset, SIGUSR1);
timespec_t timeout = {
.tv_nsec = 10000000,
.tv_sec = 0,
};
assert(sigtimedwait(&waitset, &info, &timeout) == -1);
assert(errno == EINTR);
kill(cpid, SIGUSR2);
nanosleep(&timeout, NULL);
assert(sigtimedwait(&waitset, &info, &timeout) == -1);
assert(errno == EAGAIN);

printf("Waiting for child...\n");
int status;
wait(&status);
assert(WIFEXITED(status));
assert(WEXITSTATUS(status) == 0);
return 0;
}

/* ======= signal_sigsuspend_stop ======= */
int test_signal_sigsuspend_stop(void) {
pid_t ppid = getpid();
Expand Down
2 changes: 2 additions & 0 deletions bin/utest/utest.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ int test_signal_stop(void);
int test_signal_cont_masked(void);
int test_signal_mask(void);
int test_signal_mask_nonmaskable(void);
int test_signal_sigtimedwait(void);
int test_signal_sigtimedwait_timeout(void);
int test_signal_sigsuspend(void);
int test_signal_sigsuspend_stop(void);
int test_signal_handler_mask(void);
Expand Down
5 changes: 4 additions & 1 deletion etc/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

TOPDIR = $(realpath ..)

FILES = group master.passwd .kshrc shells
FILES = group master.passwd rc.init rc.shutdown .kshrc shells
INSTALL-FILES = $(addprefix $(SYSROOT)/etc/, $(FILES))

all: build
Expand All @@ -12,3 +12,6 @@ include $(TOPDIR)/build/common.mk
$(SYSROOT)/etc/%: %
echo "[INSTALL] $(DIR)$* -> /etc/$*"
$(INSTALL) -m 644 -D $< $@

install-here:
chmod 755 $(SYSROOT)/etc/rc.*
13 changes: 13 additions & 0 deletions etc/rc.init
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/bin/ksh

umask 022

echo " __ __ _ _ _ ____ _____ "
echo " | \/ (_) (_) | / __ \ / ____| "
echo " | \ / |_ _ __ ___ _| | _____ _ __| | | | (___ "
echo " | |\/| | | '_ \` _ \| | |/ / _ \ '__| | | |\___ \ "
echo " | | | | | | | | | | | < __/ | | |__| |____) | "
echo " |_| |_|_|_| |_| |_|_|_|\_\___|_| \____/|_____/ "
echo

exec /bin/ksh
3 changes: 3 additions & 0 deletions etc/rc.shutdown
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/bin/ksh

echo "Shutdown not supported yet!"
8 changes: 8 additions & 0 deletions include/signal.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#define _SIGNAL_H_

#include <sys/cdefs.h>
#include <sys/time.h>
#include <sys/signal.h>

__BEGIN_DECLS
Expand Down Expand Up @@ -68,6 +69,13 @@ int sigsuspend(const sigset_t *);
int killpg(int pgrp, int sig);
int siginterrupt(int sig, int flag);

/*
* X/Open CAE Specification Issue 5; IEEE Std 1003.1b-1993 (POSIX)
*/
int sigwait(const sigset_t *__restrict, int *__restrict);
int sigtimedwait(const sigset_t *__restrict set, siginfo_t *__restrict info,
const struct timespec *__restrict timeout);

/*
* Mimiker specific stuff.
*/
Expand Down
3 changes: 3 additions & 0 deletions include/sys/signal.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include <sys/sigtypes.h>
#include <sys/siginfo.h>
#include <sys/time.h>

#define SIGHUP 1 /* hangup */
#define SIGINT 2 /* interrupt */
Expand Down Expand Up @@ -201,6 +202,8 @@ void sig_onexec(proc_t *p);
int do_sigaction(signo_t sig, const sigaction_t *act, sigaction_t *oldact);
int do_sigprocmask(int how, const sigset_t *set, sigset_t *oset);
int do_sigsuspend(proc_t *p, const sigset_t *mask);
int do_sigtimedwait(proc_t *p, sigset_t waitset, ksiginfo_t *kinfo,
cahirwpz marked this conversation as resolved.
Show resolved Hide resolved
struct timespec *timeout);
int do_sigpending(proc_t *p, sigset_t *set);

#endif /* !_KERNEL */
Expand Down
3 changes: 2 additions & 1 deletion include/sys/syscall.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@
#define SYS_fsync 83
#define SYS_kqueue1 84
#define SYS_kevent 85
#define SYS_MAXSYSCALL 86
#define SYS_sigtimedwait 86
#define SYS_MAXSYSCALL 87

#define SYS_MAXSYSARGS 6
7 changes: 7 additions & 0 deletions include/sys/syscallargs.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <sys/time.h>
#include <sys/ucontext.h>
#include <sys/sigtypes.h>
#include <sys/siginfo.h>
#define SCARG(p, x) ((p)->x.arg)
#define SYSCALLARG(x) union { register_t _pad; x arg; }

Expand Down Expand Up @@ -435,3 +436,9 @@ typedef struct {
SYSCALLARG(size_t) nevents;
SYSCALLARG(const struct timespec *) timeout;
} kevent_args_t;

typedef struct {
SYSCALLARG(const sigset_t *) set;
SYSCALLARG(siginfo_t *) info;
SYSCALLARG(struct timespec *) timeout;
} sigtimedwait_args_t;
56 changes: 56 additions & 0 deletions lib/libc/sys/sigwait.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/* $NetBSD: sigwait.c,v 1.5 2012/03/20 16:26:12 matt Exp $ */

/*-
* Copyright (c) 2003 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Jaromir Dolecek.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/

#include <sys/cdefs.h>
#include <sys/types.h>
#include <sys/syscall.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>

/*
* This is wrapper around sigtimedwait(2), providing sigwait()
* implementation for userland.
*/
int
sigwait(const sigset_t * __restrict set, int * __restrict signum)
{
int saved_errno, new_errno, sig;

saved_errno = errno;
sig = sigtimedwait(set, NULL, NULL);
new_errno = errno;
errno = saved_errno;
if (sig < 0)
return (new_errno);
*signum = sig;
return (0);
}
1 change: 1 addition & 0 deletions lib/libc/sys/syscalls.S
Original file line number Diff line number Diff line change
Expand Up @@ -84,3 +84,4 @@ SYSCALL(sync, SYS_sync)
SYSCALL(fsync, SYS_fsync)
SYSCALL(kqueue1, SYS_kqueue1)
SYSCALL(kevent, SYS_kevent)
SYSCALL(sigtimedwait, SYS_sigtimedwait)
9 changes: 9 additions & 0 deletions sbin/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# vim: tabstop=8 shiftwidth=8 noexpandtab:

TOPDIR = $(realpath ..)

SUBDIR = init

all: build

include $(TOPDIR)/build/common.mk
21 changes: 21 additions & 0 deletions sbin/init/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT/X Consortium License

© 2014-2015 Dimitris Papastamos <[email protected]>

Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
6 changes: 6 additions & 0 deletions sbin/init/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
TOPDIR = $(realpath ../..)

PROGRAM = init
FORMAT-EXCLUDE = $(SOURCES)

include $(TOPDIR)/build/build.prog.mk
26 changes: 26 additions & 0 deletions sbin/init/README
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
sinit - suckless init
=====================

sinit is a simple init. It was initially based on
Rich Felker's minimal init[1].

Why?
----

I wanted to get rid of Busybox init on my toy distro[2].

How?
----

There are 3 signals that sinit will act on.

SIGUSR1: powers off the machine.
SIGINT: reboots the machine (or alternatively via ctrl-alt-del).
SIGCHLD: reap children

To see how sinit integrates with the init scripts, then have
a look at [3].

[1] https://gist.github.com/rofl0r/6168719
[2] http://git.2f30.org/morpheus/
[3] http://git.2f30.org/ports/tree/fs/
5 changes: 5 additions & 0 deletions sbin/init/config.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/* See LICENSE file for copyright and license details. */

static char *const rcinitcmd[] = { "/etc/rc.init", NULL };
static char *const rcrebootcmd[] = { "/etc/rc.shutdown", "reboot", NULL };
static char *const rcpoweroffcmd[] = { "/etc/rc.shutdown", "poweroff", NULL };
Loading