shadow / shadow

Shadow is a discrete-event network simulator that directly executes real application code, enabling you to simulate distributed systems with thousands of network-connected processes in realistic and scalable private network experiments using your laptop, desktop, or server running Linux.

Home Page:https://shadow.github.io

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Support nginx workers

sporksmith opened this issue · comments

nginx currently doesn't work under shadow with workers enabled. https://shadow.github.io/docs/guide/compatibility_notes.html?highlight=nginx#nginx

Previously this was because shadow didn't support fork, but now it does.

With workers enabled, the test currently times out. The shadow.log contains these warnings:

00:00:00.010232 [416526:shadow-worker] 00:00:00.000090070 [WARN] [server:11.0.0.4] [unix.rs:2172] [shadow_rs::host::descriptor::socket::unix] We do not yet handle ioctl request FIOASYNC on unix sockets
...
00:00:19.363154 [394547:shadow-worker] 00:00:00.000000000 [WARN] [server:11.0.0.4] [syscall_handler.c:564] [syscallhandler_make_syscall] Detected unsupported syscall 130 called from thread 1000 in process nginx on host server

From socket(7):

FIOASYNC: Change the O_ASYNC flag to enable or disable asynchronous I/O mode of the socket. Asynchronous I/O mode means that the SIGIO signal or the signal set with F_SETSIG is raised when a new I/O event occurs.

signal 130 is the sigsuspend syscall. Seems likely we'd need to add that syscall. It doesn't look too bad.

stderr has:

nginx: [alert] could not open error log file: open() "/var/log/nginx/error.log" failed (13: Permission denied)
2000/01/01 00:00:00 [alert] 1000#1000: ioctl(FIOASYNC) failed while spawning "worker process" (22: Invalid argument)

So it looks like we probably need to support:

  • the FIOASYNC ioctl. This doesn't look too bad; we'd need to track whether it's set and raise SIGIO in various places if it's set. (Maybe a small number of places in the descriptor code?)
  • the sigsuspend syscall. This looks pretty straightforward, though involves setting a temporary signal mask, so we'd need to add some state somewhere to save the previous mask so that it can be restored.