Skip to main content
Sign in
Snippets Groups Projects
Select Git revision
  • fafb4ad01efde81ae6e1dfd4bc6b1cadff41a517
  • master default protected
  • hsh-2025073100
  • hsh-2025012100
  • hsh-2024111900
  • hsh-2024072400
  • hsh-2024060300
  • hsh-2024012900
  • hsh-2023121100
  • hsh-v1.1.9
  • hsh-v1.1.7
11 results

maxima_fork.c

Blame
  • maxima_fork.c 5.16 KiB
    #include <stdio.h>
    #include <string.h>
    #include <errno.h>
    #include <stdlib.h>
    #include <pwd.h>
    #include <signal.h>
    
    #include <sys/resource.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <sys/wait.h>
    
    #include <fcntl.h>
    #include <bsd/unistd.h>
    #include <limits.h>
    #include <grp.h>
    #define N_SLOT 16
    #define RNOFILE 256
    #define FILEPATH_LEN (PATH_MAX + 1)
    char filepath[FILEPATH_LEN];
    
    // inits a maxima process for web service:
    // changes gid/uid to maxima-{slot}
    // redirects input/output, creates temporary subdirectories
    char *fork_new_process() {
    	fflush(stdout);
    
    	// send an S for Synchronization, so that
    	// the server process doesn't accidentally write into
    	// sbcl's buffer
    	// the server should not write anything before it has read this
    	write(STDOUT_FILENO, "S", 1);
    
    	// while the loop is running, the SIGCHLD handler
    	// is deactivated so that children are automatically reaped
    	// after that, it is again restored
    	struct sigaction old, new;
    	new.sa_handler = SIG_IGN;
    	sigemptyset(&new.sa_mask);
    	new.sa_flags = SA_NOCLDWAIT;
    	char *ret = NULL;
    	if (sigaction(SIGCHLD, &new, &old) == -1) {
    		perror("Could not set signal error for children");
    		return NULL;
    	}
    
    	// when sbcl spawns a child process through lisp, sbcl tries to close all
    	// filedescriptors until RLIMIT_NOFILE
    	// in docker containers, this is by standard quite high, so it takes long
    	// which is remediated here by setting it lower manually
    	struct rlimit nofile = { .rlim_cur = RNOFILE, .rlim_max = RNOFILE };
    	if (setrlimit(RLIMIT_NOFILE, &nofile) == -1) {
    		perror("Error setting rlimit_nofile");
    		sigaction(SIGCHLD, &old, NULL);
    		return NULL;
    	}
    
    	for (;;) {
    		// can't flush enough
    		fflush(stdout);
    		int slot;
    		
    		// the slot number and temp directory is sent to the process
    		// over stdin in the format "%d%s", where %s can contain anything
    		// but newlines and musn't start with a number, which isn't a
    		// problem for absolute paths
    		if (scanf("%d", &slot) == EOF) {
    			if (errno != 0) {
    				perror("Error getting slot number from stdin");
    				ret = NULL;