コード例 #1
0
ファイル: crashcatcher.cpp プロジェクト: 0xmono/openmw
static void crash_catcher(int signum, siginfo_t *siginfo, void *context)
{
    //ucontext_t *ucontext = (ucontext_t*)context;
    pid_t dbg_pid;
    int fd[2];

    /* Make sure the effective uid is the real uid */
    if(getuid() != geteuid())
    {
        raise(signum);
        return;
    }

    safe_write(STDERR_FILENO, fatal_err, sizeof(fatal_err)-1);
    if(pipe(fd) == -1)
    {
        safe_write(STDERR_FILENO, pipe_err, sizeof(pipe_err)-1);
        raise(signum);
        return;
    }

    crash_info.signum = signum;
    crash_info.pid = getpid();
    crash_info.has_siginfo = !!siginfo;
    if(siginfo)
        crash_info.siginfo = *siginfo;
    if(cc_user_info)
        cc_user_info(crash_info.buf, crash_info.buf+sizeof(crash_info.buf));

    /* Fork off to start a crash handler */
    switch((dbg_pid=fork()))
    {
    /* Error */
    case -1:
        safe_write(STDERR_FILENO, fork_err, sizeof(fork_err)-1);
        raise(signum);
        return;

    case 0:
        dup2(fd[0], STDIN_FILENO);
        close(fd[0]);
        close(fd[1]);

        execl(argv0, argv0, crash_switch, NULL);

        safe_write(STDERR_FILENO, exec_err, sizeof(exec_err)-1);
        _exit(1);

    default:
#ifdef __linux__
        prctl(PR_SET_PTRACER, dbg_pid, 0, 0, 0);
#endif
        safe_write(fd[1], &crash_info, sizeof(crash_info));
        close(fd[0]);
        close(fd[1]);

        /* Wait; we'll be killed when gdb is done */
        do {
            int status;
            if(waitpid(dbg_pid, &status, 0) == dbg_pid &&
                    (WIFEXITED(status) || WIFSIGNALED(status)))
            {
                /* The debug process died before it could kill us */
                raise(signum);
                break;
            }
        } while(1);
    }
}
コード例 #2
0
ファイル: machine-pool.c プロジェクト: heftig/systemd
static int setup_machine_raw(uint64_t size, sd_bus_error *error) {
        _cleanup_free_ char *tmp = NULL;
        _cleanup_close_ int fd = -1;
        struct statvfs ss;
        pid_t pid = 0;
        siginfo_t si;
        int r;

        /* We want to be able to make use of btrfs-specific file
         * system features, in particular subvolumes, reflinks and
         * quota. Hence, if we detect that /var/lib/machines.raw is
         * not located on btrfs, let's create a loopback file, place a
         * btrfs file system into it, and mount it to
         * /var/lib/machines. */

        fd = open("/var/lib/machines.raw", O_RDWR|O_CLOEXEC|O_NONBLOCK|O_NOCTTY);
        if (fd >= 0) {
                r = fd;
                fd = -1;
                return r;
        }

        if (errno != ENOENT)
                return sd_bus_error_set_errnof(error, errno, "Failed to open /var/lib/machines.raw: %m");

        r = tempfn_xxxxxx("/var/lib/machines.raw", NULL, &tmp);
        if (r < 0)
                return r;

        (void) mkdir_p_label("/var/lib", 0755);
        fd = open(tmp, O_RDWR|O_CREAT|O_EXCL|O_NOCTTY|O_CLOEXEC, 0600);
        if (fd < 0)
                return sd_bus_error_set_errnof(error, errno, "Failed to create /var/lib/machines.raw: %m");

        if (fstatvfs(fd, &ss) < 0) {
                r = sd_bus_error_set_errnof(error, errno, "Failed to determine free space on /var/lib/machines.raw: %m");
                goto fail;
        }

        if (ss.f_bsize * ss.f_bavail < VAR_LIB_MACHINES_FREE_MIN) {
                r = sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Not enough free disk space to set up /var/lib/machines.");
                goto fail;
        }

        if (ftruncate(fd, size) < 0) {
                r = sd_bus_error_set_errnof(error, errno, "Failed to enlarge /var/lib/machines.raw: %m");
                goto fail;
        }

        pid = fork();
        if (pid < 0) {
                r = sd_bus_error_set_errnof(error, errno, "Failed to fork mkfs.btrfs: %m");
                goto fail;
        }

        if (pid == 0) {

                /* Child */

                (void) reset_all_signal_handlers();
                (void) reset_signal_mask();
                assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0);

                fd = safe_close(fd);

                execlp("mkfs.btrfs", "-Lvar-lib-machines", tmp, NULL);
                if (errno == ENOENT)
                        _exit(99);

                _exit(EXIT_FAILURE);
        }

        r = wait_for_terminate(pid, &si);
        if (r < 0) {
                sd_bus_error_set_errnof(error, r, "Failed to wait for mkfs.btrfs: %m");
                goto fail;
        }

        pid = 0;

        if (si.si_code != CLD_EXITED) {
                r = sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "mkfs.btrfs died abnormally.");
                goto fail;
        }
        if (si.si_status == 99) {
                r = sd_bus_error_set_errnof(error, ENOENT, "Cannot set up /var/lib/machines, mkfs.btrfs is missing");
                goto fail;
        }
        if (si.si_status != 0) {
                r = sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "mkfs.btrfs failed with error code %i", si.si_status);
                goto fail;
        }

        r = rename_noreplace(AT_FDCWD, tmp, AT_FDCWD, "/var/lib/machines.raw");
        if (r < 0) {
                sd_bus_error_set_errnof(error, r, "Failed to move /var/lib/machines.raw into place: %m");
                goto fail;
        }

        r = fd;
        fd = -1;

        return r;

fail:
        unlink_noerrno(tmp);

        if (pid > 1)
                kill_and_sigcont(pid, SIGKILL);

        return r;
}
コード例 #3
0
ファイル: ImageLoaderQueue.cpp プロジェクト: Lingrui/TS
void *FileLoadWorker ( void *arg )
{
  WqInfo_t *wqinfo = (WqInfo_t *)arg;
  int threadNum=wqinfo->threadNum;
  WorkerInfoQueue *q = wqinfo->wq;
  assert ( q );

  bool done = false;
  char dateStr[256];
  struct tm newtime;
  time_t ltime;
  double T1=0,T2=0,T3,T4;

  char name[20];
  sprintf(name,"FileLdWkr%d",threadNum);
  prctl(PR_SET_NAME,name,0,0,0);

  const double noiseThreshold = 0.;  // to be set by command line option
  FluidPotentialCorrector fpCorr(noiseThreshold);

  while ( !done )
  {
    WorkerInfoQueueItem item = q->GetItem();

    if ( item.finished == true )
    {
      // we are no longer needed...go away!
      done = true;
      q->DecrementDone();
      continue;
    }
    ImageLoadWorkInfo *one_img_loader = ( ImageLoadWorkInfo * ) item.private_data;

    ClockTimer timer;
    Timer tmr;
    Image *img = &one_img_loader->img[one_img_loader->cur_buffer];

    if (one_img_loader->inception_state->img_control.threaded_file_access)
    {
      tmr.restart();
      if ( !img->LoadRaw ( one_img_loader->name) )
      {
        exit ( EXIT_FAILURE );
      }

      T1=tmr.elapsed();
      tmr.restart();
      if(img->raw->imageState & IMAGESTATE_QuickPinnedPixelDetect)
        one_img_loader->pinnedInFlow->QuickUpdate ( one_img_loader->flow, img);
      else
        one_img_loader->pinnedInFlow->Update ( one_img_loader->flow, img,(ImageTransformer::gain_correction?ImageTransformer::gain_correction:0));

      T2=tmr.elapsed();
    }

    tmr.restart();


    // correct in-channel electrical cross-talk
    ImageTransformer::XTChannelCorrect ( one_img_loader->img[one_img_loader->cur_buffer].raw, one_img_loader->img[one_img_loader->cur_buffer].results_folder ); // buffer_ix

    // testing of lossy compression
    if(ImageTransformer::PCATest[0]) {
      AdvComprTest(one_img_loader->name,&one_img_loader->img[one_img_loader->cur_buffer],ImageTransformer::PCATest,false/*one_img_loader->inception_state->img_control.col_flicker_correct*/ );
    }
    // col noise correction (if done during lossy compression will already have happened.
    else if ( !(img->raw->imageState & IMAGESTATE_ComparatorCorrected) &&
              one_img_loader->inception_state->img_control.col_flicker_correct )
    {
        if( one_img_loader->inception_state->img_control.col_pair_pixel_xtalk_correct ){
            PairPixelXtalkCorrector xtalkCorrector;
            float xtalk_fraction = one_img_loader->inception_state->img_control.pair_xtalk_fraction;
            xtalkCorrector.Correct(one_img_loader->img[one_img_loader->cur_buffer].raw, xtalk_fraction);
        }
        {
      	  CorrNoiseCorrector rnc;
      	  rnc.CorrectCorrNoise(one_img_loader->img[one_img_loader->cur_buffer].raw,3,one_img_loader->inception_state->bfd_control.beadfindThumbnail );
        }


      if(one_img_loader->inception_state->bfd_control.beadfindThumbnail)
      {
        //ComparatorNoiseCorrector
        ComparatorNoiseCorrector cnc;
        cnc.CorrectComparatorNoiseThumbnail(one_img_loader->img[one_img_loader->cur_buffer].raw, one_img_loader->mask, one_img_loader->inception_state->loc_context.regionXSize,one_img_loader->inception_state->loc_context.regionYSize, one_img_loader->inception_state->img_control.col_flicker_correct_verbose);
      } else {
        ComparatorNoiseCorrector cnc;
        cnc.CorrectComparatorNoise(one_img_loader->img[one_img_loader->cur_buffer].raw, one_img_loader->mask, one_img_loader->inception_state->img_control.col_flicker_correct_verbose, one_img_loader->inception_state->img_control.aggressive_cnc,false,threadNum );
      }
    }
//#define DEBUG_IMAGE_CORR_ISSUES 1
#ifdef DEBUG_IMAGE_CORR_ISSUES

        char newName[1024];
        char *nptr,*ptr=one_img_loader->name;
        while((nptr = strstr(ptr,"/")))ptr=nptr+1;
        if(*ptr == '/')
        	ptr++;
        sprintf(newName,"%s_proc",one_img_loader->name);

        Acq saver;
        saver.SetData ( &one_img_loader->img[one_img_loader->cur_buffer] );
        saver.WriteVFC(newName, 0, 0, one_img_loader->img[one_img_loader->cur_buffer].raw->cols, one_img_loader->img[one_img_loader->cur_buffer].raw->rows);
#endif
    T3=tmr.elapsed();
    tmr.restart();

    // Fluid potential corrector
    const bool correctFluidPotential = one_img_loader->inception_state->img_control.fluid_potential_correct;
    const double noiseThreshold = (double) one_img_loader->inception_state->img_control.fluid_potential_threshold;
    if (correctFluidPotential){
        fpCorr.setThreshold(noiseThreshold);

                // parse rowsum file name to load
                const std::string datFileName = one_img_loader->name;
                printf("dat file name %s\n", datFileName.c_str());
                const size_t pos1 = datFileName.find_last_of('/');
                const size_t pos2 = datFileName.find_last_of('.');
                const std::string rowsumFileName = datFileName.substr(0, pos1) + "/../rowsum/" + datFileName.substr(pos1+1, pos2-pos1-1) + ".hwsum";
                // printf("rowsum file name %s pos1 %u pos2 %u\n", rowsumFileName.c_str(), (uint32_t) pos1, (uint32_t) pos2);


                // determine if the data file is thumbnail or block
        const bool isThumbnail = one_img_loader->inception_state->bfd_control.beadfindThumbnail;
        if(isThumbnail){
                fpCorr.setIsThumbnail();
        }

        // set image
        const unsigned int regionXSize = one_img_loader->inception_state->loc_context.regionXSize;
        const unsigned int regionYSize = one_img_loader->inception_state->loc_context.regionYSize;
        const char nucChar = one_img_loader->inception_state->flow_context.ReturnNucForNthFlow(one_img_loader->flow);
        fpCorr.setImage(one_img_loader->img[one_img_loader->cur_buffer].raw, one_img_loader->mask,  regionYSize, regionXSize, nucChar);
        //printf("nucChar is %c\n", nucChar);


        // load sensing electrode data
        if (isThumbnail){
                const unsigned int numRows = one_img_loader->img[one_img_loader->cur_buffer].raw->rows;
                fpCorr.loadSensingElectrodeDataThumbnail(rowsumFileName, numRows);

        } else {
                // determine startRow and endRow
                one_img_loader->img[one_img_loader->cur_buffer].SetOffsetFromChipOrigin(one_img_loader->name);
                const unsigned int startRow = one_img_loader->img[one_img_loader->cur_buffer].raw->chip_offset_y;
                const unsigned int endRow = startRow + one_img_loader->img[one_img_loader->cur_buffer].raw->rows;
       //         printf("offset x y = %d %d, start and end rows are %u,%u\n", one_img_loader->img[one_img_loader->cur_buffer].raw->chip_offset_x,one_img_loader->img[one_img_loader->cur_buffer].raw->chip_offset_y, startRow, endRow);
                fpCorr.loadSensingElectrodeData(rowsumFileName, startRow, endRow);
        }

        // correct fluid potential
         if (fpCorr.readRowSumIsSuccess()){
                 fpCorr.doCorrection();
         } else {
                 printf("fluidPotentialCorrector skipped:  Cannot find rowsum file %s \n", rowsumFileName.c_str());
         }

    }


    // dump dc offset one_img_loaderrmation before we do any normalization
    DumpDcOffset ( one_img_loader );
    int buffer_ix = one_img_loader->cur_buffer;

    // setting the mean of frames to zero will be done by the bkgmodel as soon as its loaded.
    img->SetMeanOfFramesToZero ( one_img_loader->normStart, one_img_loader->normEnd,0 );

    // calculate the smooth pH step amplitude in empty wells across the whole image
    if ( one_img_loader->doEmptyWellNormalization )
    {
      // this is redundant with what's in the EmptyTrace class, but this method of spatial normalization
      // is going to go away soon, so not worth fixing
      MaskType referenceMask = MaskReference;

      if ( one_img_loader->inception_state->bkg_control.trace_control.use_dud_and_empty_wells_as_reference )
        referenceMask = ( MaskType ) ( MaskReference | MaskDud );

      one_img_loader->img[buffer_ix].CalculateEmptyWellLocalScaleForFlow ( * ( one_img_loader->pinnedInFlow ),one_img_loader->mask,one_img_loader->flow,referenceMask,one_img_loader->smooth_span );
#if 0
      char fname[512];
      sprintf ( fname,"ewampimg_%04d.txt",one_img_loader->flow );
      FILE *ewampfile = fopen ( fname,"w" );
      for ( int row=0;row < one_img_loader->img[buffer_ix].GetRows();row++ )
      {
        int col;

        for ( col=0;col < ( one_img_loader->img[buffer_ix].GetCols()-1 ); col++ )
          fprintf ( ewampfile,"%9.5f\t",one_img_loader->img[buffer_ix].getEmptyWellAmplitude ( row,col ) );

        fprintf ( ewampfile,"%9.5f\n",one_img_loader->img[buffer_ix].getEmptyWellAmplitude ( row,col ) );
      }
      fclose ( ewampfile );
#endif
    }

    // dump pH step debug one_img_loader to file (its really fast, don't worry)
    DumpStep ( one_img_loader );
    if ( one_img_loader->doRawBkgSubtract )
    {
      one_img_loader->img[buffer_ix].SubtractLocalReferenceTrace ( one_img_loader->mask, MaskBead, MaskReference, one_img_loader->NNinnerx,
                                                                   one_img_loader->NNinnery,one_img_loader->NNouterx,one_img_loader->NNoutery, false, true, true );
      if ( one_img_loader->flow==0 ) // absolute first flow,not flow buffer
        printf ( "Notify user: NN empty subtraction in effect.  No further warnings will be given. %d \n",one_img_loader->flow );
    }
    T4=tmr.elapsed();

    //    printf ( "Allow model to go %d \n", one_img_loader->flow );

    SetReadCompleted(one_img_loader);

    size_t usec = timer.GetMicroSec();

    ltime=time(&ltime);
    localtime_r(&ltime, &newtime);
    strftime(dateStr,sizeof(dateStr),"%H:%M:%S", &newtime);

    fprintf ( stdout, "FileLoadWorker: ImageProcessing time for flow %d: %0.2lf(ld=%.2f pin=%.2f cnc=%.2f xt=%.2f sem=%.2lf cache=%.2lf) sec %s\n",
              one_img_loader->flow , usec / 1.0e6, T1, T2, T3, T4, img->SemaphoreWaitTime, img->CacheAccessTime, dateStr);
    fflush(stdout);
    q->DecrementDone();
  }

  return ( NULL );
}
コード例 #4
0
ファイル: prctl02.c プロジェクト: 1587/ltp
int main(int ac, char **av)
{

	int lc, i;
	pid_t child_pid;
	int status;

	tst_parse_opts(ac, av, NULL, NULL);

	setup();

	for (lc = 0; TEST_LOOPING(lc); lc++) {

		tst_count = 0;

		for (i = 0; i < TST_TOTAL; ++i) {

			switch (child_pid = FORK_OR_VFORK()) {

			case -1:
				/* fork() failed */
				tst_resm(TFAIL, "fork() failed");
				continue;

			case 0:
				/* Child */

				TEST(prctl(test_cases[i].option,
					   test_cases[i].arg2));
				if ((TEST_RETURN == -1) && (TEST_ERRNO ==
							    test_cases
							    [i].exp_errno)) {
					exit(TEST_ERRNO);
				} else {
					tst_resm(TWARN | TTERRNO,
						 "prctl() returned %ld",
						 TEST_RETURN);
					exit(TEST_ERRNO);
				}

			default:
				/* Parent */
				if ((waitpid(child_pid, &status, 0)) < 0) {
					tst_resm(TFAIL, "waitpid() failed");
					continue;
				}

				if ((WIFEXITED(status)) && (WEXITSTATUS(status)
							    ==
							    test_cases
							    [i].exp_errno)) {
					tst_resm(TPASS, "Test Passed");
				} else {
					tst_resm(TFAIL, "Test Failed");
				}

			}
		}
	}

	/* cleanup and exit */
	cleanup();

	tst_exit();

}
コード例 #5
0
ファイル: join.c プロジェクト: Sidnioulz/firejail
void join(pid_t pid, const char *homedir, int argc, char **argv, int index) {
	extract_command(argc, argv, index);

	// if the pid is that of a firejail  process, use the pid of the first child process
	char *comm = pid_proc_comm(pid);
	if (comm) {
		// remove \n
		char *ptr = strchr(comm, '\n');
		if (ptr)
			*ptr = '\0';
		if (strcmp(comm, "firejail") == 0) {
			pid_t child;
			if (find_child(pid, &child) == 0) {
				pid = child;
				printf("Switching to pid %u, the first child process inside the sandbox\n", (unsigned) pid);
			}
		}
		free(comm);
	}

	// check privileges for non-root users
	uid_t uid = getuid();
	if (uid != 0) {
		uid_t sandbox_uid = pid_get_uid(pid);
		if (uid != sandbox_uid) {
			exechelp_logerrv("firejail", FIREJAIL_ERROR, "Error: permission is denied to join a sandbox created by a different user.\n");
			exit(1);
		}
	}

	// in user mode set caps seccomp, cpu, cgroup, etc
	if (getuid() != 0) {
		extract_caps_seccomp(pid);
		extract_cpu(pid);
		extract_cgroup(pid);
		extract_nogroups(pid);
		extract_user_namespace(pid);
	}
	
	// set cgroup
	if (cfg.cgroup)
		set_cgroup(cfg.cgroup);
		
	// join namespaces
	if (join_namespace(pid, "ipc"))
		exit(1);
	if (join_namespace(pid, "net"))
		exit(1);
	if (join_namespace(pid, "pid"))
		exit(1);
	if (join_namespace(pid, "uts"))
		exit(1);
	if (join_namespace(pid, "mnt"))
		exit(1);

	pid_t child = fork();
	if (child < 0)
		errExit("fork");
	if (child == 0) {
		// chroot into /proc/PID/root directory
		char *rootdir;
		if (asprintf(&rootdir, "/proc/%d/root", pid) == -1)
			errExit("asprintf");
			
		int rv = chroot(rootdir); // this will fail for processes in sandboxes not started with --chroot option
		if (rv == 0)
			printf("changing root to %s\n", rootdir);
		
		prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); // kill the child in case the parent died
		if (chdir("/") < 0)
			errExit("chdir");
		if (homedir) {
			struct stat s;
			if (stat(homedir, &s) == 0) {
				/* coverity[toctou] */
				if (chdir(homedir) < 0)
					errExit("chdir");
			}
		}
		
		// set cpu affinity
		if (cfg.cpus)
			set_cpu_affinity();
					
		// set caps filter
		if (apply_caps == 1)
			caps_set(caps);
#ifdef HAVE_SECCOMP
		// set seccomp filter
		if (apply_seccomp == 1)
			seccomp_set();
#endif


    /* We then load the variables that the original Firejail instance applied
     * to the original Firejail client whose namespace we're joining. */
    load_domain_env_from_chroot_proc();

		// mount user namespace or drop privileges
		if (arg_noroot) {
			if (arg_debug)
				printf("Joining user namespace\n");
			if (join_namespace(1, "user"))
				exit(1);
		}
		else 
			drop_privs(arg_nogroups);

		// set prompt color to green
		//export PS1='\[\e[1;32m\][\u@\h \W]\$\[\e[0m\] '
		if (setenv("PROMPT_COMMAND", "export PS1=\"\\[\\e[1;32m\\][\\u@\\h \\W]\\$\\[\\e[0m\\] \"", 1) < 0)
			errExit("setenv");

		// run icmdline trough /bin/bash
		if (cfg.command_line == NULL)
			// replace the process with a regular bash session
			execlp("/bin/bash", "/bin/bash", NULL);
		else {
			// run the command supplied by the user
			int cwd = 0;
			if (cfg.cwd) {
				if (chdir(cfg.cwd) == 0)
					cwd = 1;
			}
			
			if (!cwd) {
				if (chdir("/") < 0)
					errExit("chdir");
				if (cfg.homedir) {
					struct stat s;
					if (stat(cfg.homedir, &s) == 0) {
						if (chdir(cfg.homedir) < 0)
							errExit("chdir");
					}
				}
			}

			char *arg[5];
			arg[0] = "/bin/bash";
			arg[1] = "-c";
			if (arg_debug)
				printf("Starting %s\n", cfg.command_line);
      exechelp_logv("firejail", "Starting %s in sandbox %d\n", cfg.command_line, pid);
			if (!arg_doubledash) {
				arg[2] = cfg.command_line;
				arg[3] = NULL;
			}
			else {
				arg[2] = "--";
				arg[3] = cfg.command_line;
				arg[4] = NULL;
			}
			execvp("/bin/bash", arg);
		}

		// it will never get here!!!
	}

	// wait for the child to finish
	waitpid(child, NULL, 0);
	exit(0);
}
コード例 #6
0
status_t AMRWriter::threadFunc() {
    mEstimatedDurationUs = 0;
    mEstimatedSizeBytes = 0;
    bool stoppedPrematurely = true;
    int64_t previousPausedDurationUs = 0;
    int64_t maxTimestampUs = 0;
    status_t err = OK;

    prctl(PR_SET_NAME, (unsigned long)"AMRWriter", 0, 0, 0);
    while (!mDone) {
        MediaBuffer *buffer;
        err = mSource->read(&buffer);

        if (err != OK) {
            break;
        }

        if (mPaused) {
            buffer->release();
            buffer = NULL;
            continue;
        }

        mEstimatedSizeBytes += buffer->range_length();
        if (exceedsFileSizeLimit()) {
            buffer->release();
            buffer = NULL;
            notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0);
            break;
        }

        int64_t timestampUs;
        CHECK(buffer->meta_data()->findInt64(kKeyTime, &timestampUs));
        if (timestampUs > mEstimatedDurationUs) {
            mEstimatedDurationUs = timestampUs;
        }
        if (mResumed) {
            previousPausedDurationUs += (timestampUs - maxTimestampUs - 20000);
            mResumed = false;
        }
        timestampUs -= previousPausedDurationUs;
        LOGV("time stamp: %lld, previous paused duration: %lld",
                timestampUs, previousPausedDurationUs);
        if (timestampUs > maxTimestampUs) {
            maxTimestampUs = timestampUs;
        }

        if (exceedsFileDurationLimit()) {
            buffer->release();
            buffer = NULL;
            notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0);
            break;
        }
        ssize_t n = write(mFd,
                        (const uint8_t *)buffer->data() + buffer->range_offset(),
                        buffer->range_length());

        if (n < (ssize_t)buffer->range_length()) {
            buffer->release();
            buffer = NULL;

            break;
        }

        // XXX: How to tell it is stopped prematurely?
        if (stoppedPrematurely) {
            stoppedPrematurely = false;
        }

        buffer->release();
        buffer = NULL;
    }

    if (stoppedPrematurely) {
        notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS, UNKNOWN_ERROR);
    }

    close(mFd);
    mFd = -1;
    mReachedEOS = true;
    if ((err == ERROR_END_OF_STREAM) || (err = -ETIMEDOUT)){
        return OK;
    }
    return err;
}
コード例 #7
0
/**************************** SUBROUTINES ******************************/
int main()
{
        int sfd, device_type, channel,num_of_3g;
        struct sockaddr_in saddr;
        socklen_t len;
	pthread_t wifi, threeg;
	char name[16];
	

        init_vrms_connection();
        init_logging_network_changes();	
#if 0
	while(1){

		send_vrms_data("wlan0", 5);
		printf("wlan0 sent\n");
		sleep(30);
		send_vrms_data("ppp1", 4);
		printf("ppp1 sent\n");
		sleep(22);
#if 0
		send_vrms_data("ppp1", 4);
		printf("wlan0 sent\n");
		sleep(30);
		send_vrms_data("ppp2", 4);
		printf("ppp2 sent\n");
		sleep(30);
#endif
		send_vrms_data("ppp2", 4);
		printf("ppp2 sent\n");
		sleep(20);
	}
#endif
	openlog("SeaMo:VHO", LOG_PID, LOG_DAEMON);

	/* Obtain a D-Bus connection handler for all D-Bus activities */
	conn = (DBusConnection *) get_connection();

        init_3g_connections();
	/* socket creation for communication with vrms. (earlier this was 
  	   done in get_current_network every time it was called which is not
 	   necessary)*/
 /* Connect to the available modems */
	connect_all_modems(conn); 
	/* Check if the system is currently connected to any network */
	while (!isconnected(conn)) {
		syslog(LOG_WARNING,
		       "Please connect to any available network\n");
		sleep(1);
	}
/*
	char *active_conn[30];
	get_active_conn(conn, active_conn);

	while (1) {
		syslog(LOG_INFO, "Inside while\n");
		int conn_state = get_active_conn_state(conn, *active_conn);
		if (conn_state == 0 || conn_state == -1)	//Unknown state
			syslog(LOG_ERR, "Not Connected to any network\n");
		else if (conn_state == CONNECTED)
			break;
		else if (conn_state == ACTIVATING)
			continue;
	}
*/
	system ("sh /usr/local/seamo/sbin/ip_rules_all.sh");	

	/* Create threads to receive data from pre-handoff */
	if (pthread_create(&threeg, NULL, threeg_data, NULL)) {
		syslog(LOG_ERR, "error in server threads\n");
	}
	if (pthread_create(&wifi, NULL, wifi_data, NULL)) {
		syslog(LOG_ERR, "error in server threads\n");
	}

	read_config();

	/* Get the signal when the parent process dies */
	prctl(PR_SET_PDEATHSIG, SIGHUP);


	while (1) {
		wifi_avail = wifi_param();

      	
                num_of_3g = get_num_of_modems(conn);
          
                if ( num_of_3g >=1){
               	threeg_avail = threeg_param();
                }
                
                else {
                   threeg_avail == -1 ;
                   }



		syslog(LOG_INFO, "wifi_avail: %d, threeg_avail: %d\n",
		       wifi_avail, threeg_avail);

		if (wifi_avail == 1 || threeg_avail == 1) {
			get_current_network(&device_type, name, &channel);

#ifdef DEBUG_L1
			syslog(LOG_INFO, "Current network: %s %d\n", name,
			       channel);
#endif

			/* If currently connected to Wi-Fi then keep the network
			 * under Observation. If the network conditions goes down
			 * then trigger the algorithm. But in case of 3G we dont 
			 * keep the network under observation, because 3G is assumed
			 * to be every where, the conditions of 3G will remain almost
			 * the same, hence we look for better Wi-Fi instead of waiting 
			 * for 3G network to degrade  */
			sleep(1);
			if (device_type == WIFI) {
				observe_wifi(name, channel);
				vho_trigger();
			} else if (device_type == GSM){
				observe_3g(name);
				vho_trigger();
			}
		}

		/* Check if parent process is alive */
		if (getppid() == 1)
			kill(getpid(), SIGHUP);
	}
	closelog();
	return 0;
}
コード例 #8
0
ファイル: linux-core.c プロジェクト: sjw7453584/Server
void uv__set_process_title(const char* title) {
#if defined(PR_SET_NAME)
  prctl(PR_SET_NAME, title);  /* Only copies first 16 characters. */
#endif
}
コード例 #9
0
ファイル: main.c プロジェクト: Gardenya/deadbeef
int
main (int argc, char *argv[]) {
    int portable = 0;
#if STATICLINK
    int staticlink = 1;
#else
    int staticlink = 0;
#endif
#if PORTABLE
    portable = 1;
    if (!realpath (argv[0], dbinstalldir)) {
        strcpy (dbinstalldir, argv[0]);
    }
    char *e = strrchr (dbinstalldir, '/');
    if (e) {
        *e = 0;
    }
    else {
        fprintf (stderr, "couldn't determine install folder from path %s\n", argv[0]);
        exit (-1);
    }
#else
    if (!realpath (argv[0], dbinstalldir)) {
        strcpy (dbinstalldir, argv[0]);
    }
    char *e = strrchr (dbinstalldir, '/');
    if (e) {
        *e = 0;
        struct stat st;
        char checkpath[PATH_MAX];
        snprintf (checkpath, sizeof (checkpath), "%s/.ddb_portable", dbinstalldir);
        if (!stat (checkpath, &st)) {
            if (S_ISREG (st.st_mode)) {
                portable = 1;
            }
        }
    }
    if (!portable) {
        strcpy (dbinstalldir, PREFIX);
    }
#endif

#ifdef __GLIBC__
    signal (SIGSEGV, sigsegv_handler);
#endif
    setlocale (LC_ALL, "");
    setlocale (LC_NUMERIC, "C");
#ifdef ENABLE_NLS
//    fprintf (stderr, "enabling gettext support: package=" PACKAGE ", dir=" LOCALEDIR "...\n");
    if (portable) {
        char localedir[PATH_MAX];
        snprintf (localedir, sizeof (localedir), "%s/locale", dbinstalldir);
        bindtextdomain (PACKAGE, localedir);
    }
    else {
        bindtextdomain (PACKAGE, LOCALEDIR);
    }
	bind_textdomain_codeset (PACKAGE, "UTF-8");
	textdomain (PACKAGE);
#endif

    fprintf (stderr, "starting deadbeef " VERSION "%s%s\n", staticlink ? " [static]" : "", portable ? " [portable]" : "");
    srand (time (NULL));
#ifdef __linux__
    prctl (PR_SET_NAME, "deadbeef-main", 0, 0, 0, 0);
#endif

#if PORTABLE_FULL
    if (snprintf (confdir, sizeof (confdir), "%s/config", dbinstalldir) > sizeof (confdir)) {
        fprintf (stderr, "fatal: too long install path %s\n", dbinstalldir);
        return -1;
    }

    strcpy (dbconfdir, confdir);
#else
    char *homedir = getenv ("HOME");
    if (!homedir) {
        fprintf (stderr, "unable to find home directory. stopping.\n");
        return -1;
    }

    char *xdg_conf_dir = getenv ("XDG_CONFIG_HOME");
    if (xdg_conf_dir) {
        if (snprintf (confdir, sizeof (confdir), "%s", xdg_conf_dir) > sizeof (confdir)) {
            fprintf (stderr, "fatal: XDG_CONFIG_HOME value is too long: %s\n", xdg_conf_dir);
            return -1;
        }
    }
    else {
        if (snprintf (confdir, sizeof (confdir), "%s/.config", homedir) > sizeof (confdir)) {
            fprintf (stderr, "fatal: HOME value is too long: %s\n", homedir);
            return -1;
        }
    }
    if (snprintf (dbconfdir, sizeof (dbconfdir), "%s/deadbeef", confdir) > sizeof (dbconfdir)) {
        fprintf (stderr, "fatal: out of memory while configuring\n");
        return -1;
    }
    mkdir (confdir, 0755);
#endif


    if (portable) {
        if (snprintf (dbdocdir, sizeof (dbdocdir), "%s/doc", dbinstalldir) > sizeof (dbdocdir)) {
            fprintf (stderr, "fatal: too long install path %s\n", dbinstalldir);
            return -1;
        }
#ifdef HAVE_COCOAUI
        char respath[PATH_MAX];
        cocoautil_get_resources_path (respath, sizeof (respath));
        if (snprintf (dbplugindir, sizeof (dbplugindir), "%s", respath) > sizeof (dbplugindir)) {
            fprintf (stderr, "fatal: too long install path %s\n", dbinstalldir);
            return -1;
        }
#else
        if (snprintf (dbplugindir, sizeof (dbplugindir), "%s/plugins", dbinstalldir) > sizeof (dbplugindir)) {
            fprintf (stderr, "fatal: too long install path %s\n", dbinstalldir);
            return -1;
        }
#endif
        if (snprintf (dbpixmapdir, sizeof (dbpixmapdir), "%s/pixmaps", dbinstalldir) > sizeof (dbpixmapdir)) {
            fprintf (stderr, "fatal: too long install path %s\n", dbinstalldir);
            return -1;
        }
        mkdir (dbplugindir, 0755);
    }
    else {
        if (snprintf (dbdocdir, sizeof (dbdocdir), "%s", DOCDIR) > sizeof (dbdocdir)) {
            fprintf (stderr, "fatal: too long install path %s\n", dbinstalldir);
            return -1;
        }
        if (snprintf (dbplugindir, sizeof (dbplugindir), "%s/deadbeef", LIBDIR) > sizeof (dbplugindir)) {
            fprintf (stderr, "fatal: too long install path %s\n", dbinstalldir);
            return -1;
        }
        if (snprintf (dbpixmapdir, sizeof (dbpixmapdir), "%s/share/deadbeef/pixmaps", PREFIX) > sizeof (dbpixmapdir)) {
            fprintf (stderr, "fatal: too long install path %s\n", dbinstalldir);
            return -1;
        }
    }

    for (int i = 1; i < argc; i++) {
        // help, version and nowplaying are executed with any filter
        if (!strcmp (argv[i], "--help") || !strcmp (argv[i], "-h")) {
            print_help ();
            return 0;
        }
        else if (!strcmp (argv[i], "--version")) {
            fprintf (stderr, "DeaDBeeF " VERSION " Copyright © 2009-2013 Alexey Yakovenko\n");
            return 0;
        }
        else if (!strcmp (argv[i], "--gui")) {
            if (i == argc-1) {
                break;
            }
            i++;
            strncpy (use_gui_plugin, argv[i], sizeof(use_gui_plugin) - 1);
            use_gui_plugin[sizeof(use_gui_plugin) - 1] = 0;
        }
    }

    trace ("installdir: %s\n", dbinstalldir);
    trace ("confdir: %s\n", confdir);
    trace ("docdir: %s\n", dbdocdir);
    trace ("plugindir: %s\n", dbplugindir);
    trace ("pixmapdir: %s\n", dbpixmapdir);

    mkdir (dbconfdir, 0755);

    int size = 0;
    char *cmdline = prepare_command_line (argc, argv, &size);

    // try to connect to remote player
    int s, len;
    struct sockaddr_un remote;

    if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
        perror("socket");
        exit(1);
    }

    memset (&remote, 0, sizeof (remote));
    remote.sun_family = AF_UNIX;
#if USE_ABSTRACT_SOCKET_NAME
    memcpy (remote.sun_path, server_id, sizeof (server_id));
    len = offsetof(struct sockaddr_un, sun_path) + sizeof (server_id)-1;
#else
    char *socketdirenv = getenv ("DDB_SOCKET_DIR");
    snprintf (remote.sun_path, sizeof (remote.sun_path), "%s/socket", socketdirenv ? socketdirenv : dbconfdir);
    len = offsetof(struct sockaddr_un, sun_path) + strlen (remote.sun_path);
#endif
    if (connect(s, (struct sockaddr *)&remote, len) == 0) {
        // pass args to remote and exit
        if (send(s, cmdline, size, 0) == -1) {
            perror ("send");
            exit (-1);
        }
        // end of message
        shutdown(s, SHUT_WR);

        int sz = -1;
        char *out = read_entire_message(s, &sz);
        if (sz == -1) {
            fprintf (stderr, "failed to pass args to remote!\n");
            exit (-1);
        }
        else {
            // check if that's nowplaying response
            const char np[] = "nowplaying ";
            const char err[] = "error ";
            if (!strncmp (out, np, sizeof (np)-1)) {
                const char *prn = &out[sizeof (np)-1];
                fwrite (prn, 1, strlen (prn), stdout);
            }
            else if (!strncmp (out, err, sizeof (err)-1)) {
                const char *prn = &out[sizeof (err)-1];
                fwrite (prn, 1, strlen (prn), stderr);
            }
            else if (sz > 0 && out[0]) {
                fprintf (stderr, "%s\n", out);
            }
        }
        if (out) {
            free (out);
        }
        close (s);
        exit (0);
    }
//    else {
//        perror ("INFO: failed to connect to existing session:");
//    }
    close(s);

    // become a server
    if (server_start () < 0) {
        exit (-1);
    }

    // hack: report nowplaying
    if (!strcmp (cmdline, "--nowplaying")) {
        char nothing[] = "nothing";
        fwrite (nothing, 1, sizeof (nothing)-1, stdout);
        return 0;
    }

    pl_init ();
    conf_init ();
    conf_load (); // required by some plugins at startup

    if (use_gui_plugin[0]) {
        conf_set_str ("gui_plugin", use_gui_plugin);
    }

    conf_set_str ("deadbeef_version", VERSION);

    volume_set_db (conf_get_float ("playback.volume", 0)); // volume need to be initialized before plugins start

    messagepump_init (); // required to push messages while handling commandline
    if (plug_load_all ()) { // required to add files to playlist from commandline
        exit (-1);
    }
    pl_load_all ();
    plt_set_curr_idx (conf_get_int ("playlist.current", 0));

    // execute server commands in local context
    int noloadpl = 0;
    if (argc > 1) {
        int res = server_exec_command_line (cmdline, size, NULL, 0);
        // some of the server commands ran on 1st instance should terminate it
        if (res == 2) {
            noloadpl = 1;
        }
        else if (res > 0) {
            exit (0);
        }
        else if (res < 0) {
            exit (-1);
        }
    }

    free (cmdline);

#if 0
    signal (SIGTERM, sigterm_handler);
    atexit (atexit_handler); // helps to save in simple cases
#endif

    streamer_init ();

    plug_connect_all ();
    messagepump_push (DB_EV_PLUGINSLOADED, 0, 0, 0);

    if (!noloadpl) {
        restore_resume_state ();
    }

    server_tid = thread_start (server_loop, NULL);

    mainloop_tid = thread_start (mainloop_thread, NULL);

    DB_plugin_t *gui = plug_get_gui ();
    if (gui) {
        gui->start ();
    }

    fprintf (stderr, "gui plugin has quit; waiting for mainloop thread to finish\n");
    thread_join (mainloop_tid);

    // terminate server and wait for completion
    if (server_tid) {
        server_terminate = 1;
        thread_join (server_tid);
        server_tid = 0;
    }

    // save config
    pl_save_all ();
    conf_save ();

    // delete legacy session file
    {
        char sessfile[1024]; // $HOME/.config/deadbeef/session
        if (snprintf (sessfile, sizeof (sessfile), "%s/deadbeef/session", confdir) < sizeof (sessfile)) {
            unlink (sessfile);
        }
    }

    // stop receiving messages from outside
    server_close ();

    // plugins might still hold references to playitems,
    // and query configuration in background
    // so unload everything 1st before final cleanup
    plug_disconnect_all ();
    plug_unload_all ();

    // at this point we can simply do exit(0), but let's clean up for debugging
    pl_free (); // may access conf_*
    conf_free ();

    fprintf (stderr, "messagepump_free\n");
    messagepump_free ();
    fprintf (stderr, "plug_cleanup\n");
    plug_cleanup ();

    fprintf (stderr, "hej-hej!\n");

    return 0;
}
コード例 #10
0
static void* a2dp_thread(void *d)
{
	struct bluetooth_data* data = (struct bluetooth_data*)d;
	a2dp_command_t command = A2DP_CMD_NONE;
	int err = 0;

	DBG("a2dp_thread started");
	prctl(PR_SET_NAME, (int)"a2dp_thread", 0, 0, 0);

	pthread_mutex_lock(&data->mutex);

	data->started = 1;
	pthread_cond_signal(&data->thread_start);

	while (1)
	{
		while (1) {
			pthread_cond_wait(&data->thread_wait, &data->mutex);

			/* Initialization needed */
			if (data->state == A2DP_STATE_NONE &&
				data->command != A2DP_CMD_QUIT) {
				err = bluetooth_init(data);
			}

			/* New state command signaled */
			if (command != data->command) {
				command = data->command;
				break;
			}
		}

		switch (command) {
			case A2DP_CMD_CONFIGURE:
				if (data->state != A2DP_STATE_INITIALIZED)
					break;
				err = bluetooth_configure(data);
				break;

			case A2DP_CMD_START:
				if (data->state != A2DP_STATE_CONFIGURED)
					break;
				err = bluetooth_start(data);
				break;

			case A2DP_CMD_STOP:
				if (data->state != A2DP_STATE_STARTED)
					break;
				err = bluetooth_stop(data);
				break;

			case A2DP_CMD_QUIT:
				bluetooth_close(data);
				sbc_finish(&data->sbc);
				a2dp_free(data);
				goto done;

			case A2DP_CMD_INIT:
				/* already called bluetooth_init() */
			default:
				break;
		}
		// reset last command in case of error to allow
		// re-execution of the same command
		if (err < 0) {
			command = A2DP_CMD_NONE;
		}
	}

done:
	pthread_mutex_unlock(&data->mutex);
	DBG("a2dp_thread finished");
	return NULL;
}
コード例 #11
0
void *AudioALSACaptureDataProviderEchoRefExt::readThread(void *arg)
{
    status_t retval = NO_ERROR;
    AudioALSACaptureDataProviderEchoRefExt *pDataProvider = static_cast<AudioALSACaptureDataProviderEchoRefExt *>(arg);

    uint32_t open_index = pDataProvider->mOpenIndex;

    char nameset[32];
    sprintf(nameset, "%s%d", __FUNCTION__, pDataProvider->mCaptureDataProviderType);
    prctl(PR_SET_NAME, (unsigned long)nameset, 0, 0, 0);

#ifdef MTK_AUDIO_ADJUST_PRIORITY
    // force to set priority
    struct sched_param sched_p;
    sched_getparam(0, &sched_p);
    sched_p.sched_priority = RTPM_PRIO_AUDIO_RECORD + 5;
    if (0 != sched_setscheduler(0, SCHED_RR, &sched_p))
    {
        ALOGE("[%s] failed, errno: %d", __FUNCTION__, errno);
    }
    else
    {
        sched_p.sched_priority = RTPM_PRIO_AUDIO_RECORD + 5;
        sched_getparam(0, &sched_p);
        ALOGD("sched_setscheduler ok, priority: %d", sched_p.sched_priority);
    }
#endif
    ALOGD("+%s(), pid: %d, tid: %d, kReadBufferSize=%x", __FUNCTION__, getpid(), gettid(), kReadBufferSize);

    // read raw data from alsa driver
    char linear_buffer[kReadBufferSize];
    while (pDataProvider->mEnable == true)
    {
        if (open_index != pDataProvider->mOpenIndex)
        {
            ALOGD("%s(), open_index(%d) != mOpenIndex(%d), return", __FUNCTION__, open_index, pDataProvider->mOpenIndex);
            break;
        }

        retval = pDataProvider->mEnableLock.lock_timeout(300);
        ASSERT(retval == NO_ERROR);
        if (pDataProvider->mEnable == false)
        {
            pDataProvider->mEnableLock.unlock();
            break;
        }

        ASSERT(pDataProvider->mPcm != NULL);
        clock_gettime(CLOCK_REALTIME, &pDataProvider->mNewtime);
        pDataProvider->timerec[0] = calc_time_diff(pDataProvider->mNewtime, pDataProvider->mOldtime);
        pDataProvider->mOldtime = pDataProvider->mNewtime;

        int retval = pcm_read(pDataProvider->mPcm, linear_buffer, kReadBufferSize);
        if (retval != 0)
        {
            ALOGE("%s(), pcm_read() error, retval = %d", __FUNCTION__, retval);
        }

        clock_gettime(CLOCK_REALTIME, &pDataProvider->mNewtime);
        pDataProvider->timerec[1] = calc_time_diff(pDataProvider->mNewtime, pDataProvider->mOldtime);
        pDataProvider->mOldtime = pDataProvider->mNewtime;

        pDataProvider->GetCaptureTimeStamp(&pDataProvider->mStreamAttributeSource.Time_Info, kReadBufferSize);

        // use ringbuf format to save buffer info
        pDataProvider->mPcmReadBuf.pBufBase = linear_buffer;
        pDataProvider->mPcmReadBuf.bufLen   = kReadBufferSize + 1; // +1: avoid pRead == pWrite
        pDataProvider->mPcmReadBuf.pRead    = linear_buffer;
        pDataProvider->mPcmReadBuf.pWrite   = linear_buffer + kReadBufferSize;
        pDataProvider->mEnableLock.unlock();

        //Provide EchoRef data
#if 0   //for check the echoref data got
        pDataProvider->provideCaptureDataToAllClients(open_index);
#else
        pDataProvider->provideEchoRefCaptureDataToAllClients(open_index);
#endif
        clock_gettime(CLOCK_REALTIME, &pDataProvider->mNewtime);
        pDataProvider->timerec[2] = calc_time_diff(pDataProvider->mNewtime, pDataProvider->mOldtime);
        pDataProvider->mOldtime = pDataProvider->mNewtime;
        ALOGD("%s, latency_in_us,%1.6lf,%1.6lf,%1.6lf", __FUNCTION__, pDataProvider->timerec[0], pDataProvider->timerec[1], pDataProvider->timerec[2]);
    }

    ALOGD("-%s(), pid: %d, tid: %d", __FUNCTION__, getpid(), gettid());
    pthread_exit(NULL);
    return NULL;
}
コード例 #12
0
ファイル: diod.c プロジェクト: alepharchives/diod-ether
static void
_service_run (srvmode_t mode, int rfdno, int wfdno)
{
    List l = diod_conf_get_listen ();
    int nwthreads = diod_conf_get_nwthreads ();
    int flags = diod_conf_get_debuglevel ();
    uid_t euid = geteuid ();
    int n;

    ss.mode = mode;
    ss.rfdno = rfdno;
    ss.wfdno = wfdno;
    ss.shutdown = 0;
    ss.reload = 0;
    _service_sigsetup ();

    ss.fds = NULL;
    ss.nfds = 0;
    switch (mode) {
        case SRV_FILEDES:
            break;
        case SRV_NORMAL:
            if (!diod_sock_listen_hostports (l, &ss.fds, &ss.nfds, NULL))
                msg_exit ("failed to set up listen ports");
#if WITH_RDMATRANS
            ss.rdma = diod_rdma_create ();
            diod_rdma_listen (ss.rdma);
#endif
#if WITH_ETHERTRANS
            ss.ether = diod_ether_create();
            diod_ether_listen(ss.ether);
#endif
            break;
    }

    /* manipulate squash/runas users if not root */
    if (euid != 0) {
        if (diod_conf_get_allsquash ()) {
            struct passwd *pw = getpwuid (euid);
            char *su = diod_conf_get_squashuser ();
            if (!pw)
                msg_exit ("getpwuid on effective uid failed");
            if (strcmp (pw->pw_name, su) != 0) {
                if (strcmp (su, DFLT_SQUASHUSER) != 0)
                    msg ("changing squashuser '%s' to '%s' "
                         "since you are not root", su, pw->pw_name);
                diod_conf_set_squashuser (pw->pw_name); /* fixes issue 41 */
            }
        } else { /* N.B. runasuser cannot be set in the config file */
            uid_t ruid = diod_conf_get_runasuid ();
            if (diod_conf_opt_runasuid () && ruid != euid)
                msg ("changing runasuid %d to %d "
                     "since you are not root", ruid, euid);
            diod_conf_set_runasuid (euid);
        }
    }
        
    if (!diod_conf_get_foreground () && mode == SRV_NORMAL)
        _daemonize (); /* implicit fork - no pthreads before this */
    if (!diod_conf_get_foreground () && mode != SRV_FILEDES)
        diod_log_set_dest (diod_conf_get_logdest ());

    /* drop root */
    if (euid == 0) {
        if (diod_conf_get_allsquash ())
            _become_user (diod_conf_get_squashuser (), -1, 1);
        else if (diod_conf_opt_runasuid ())
            _become_user (NULL, diod_conf_get_runasuid (), 1);
    }

    /* clear umask */
    umask (0);

    flags |= SRV_FLAGS_LOOSEFID;        /* work around buggy clients */
    flags |= SRV_FLAGS_AUTHCONN;
    //flags |= SRV_FLAGS_FLUSHSIG;      /* XXX temporarily off */
    if (geteuid () == 0) {
        flags |= SRV_FLAGS_SETFSID;
        flags |= SRV_FLAGS_DAC_BYPASS;
        if (_test_setgroups ())
            flags |= SRV_FLAGS_SETGROUPS;
        else
            msg ("test_setgroups: groups are per-process (disabling)");
    }

    /* Process dumpable flag may have been cleared by uid manipulation above.
     * Set it here, then maintain it in user.c::np_setfsid () as uids are
     * further manipulated.
     */
    if (prctl (PR_SET_DUMPABLE, 1, 0, 0, 0) < 0)
        err_exit ("prctl PR_SET_DUMPABLE failed");

    if (!diod_conf_get_userdb ())
        flags |= SRV_FLAGS_NOUSERDB;
    if (!(ss.srv = np_srv_create (nwthreads, flags))) /* starts threads */
        errn_exit (np_rerror (), "np_srv_create");
    if (diod_init (ss.srv) < 0)
        errn_exit (np_rerror (), "diod_init");

    if ((n = pthread_create (&ss.t, NULL, _service_loop, NULL)))
        errn_exit (n, "pthread_create _service_loop");
#if WITH_RDMATRANS
    if ((n = pthread_create (&ss.rdma_t, NULL, _service_loop_rdma, NULL)))
        errn_exit (n, "pthread_create _service_loop_rdma");
#endif
#if WITH_ETHERTRANS
    if ((n = pthread_create (&ss.ether_t, NULL, _service_loop_ether, NULL)))
        errn_exit (n, "pthread_create _service_loop_ether");
#endif
    switch (mode) {
        case SRV_FILEDES:
            np_srv_wait_conncount (ss.srv, 1);
            pthread_kill (ss.t, SIGUSR1);
            break;
        case SRV_NORMAL:
            break;
    }
    if ((n = pthread_join (ss.t, NULL)))
        errn_exit (n, "pthread_join _service_loop");
#if WITH_RDMATRANS
    if ((n = pthread_join (ss.rdma_t, NULL)))
        errn_exit (n, "pthread_join _service_loop_rdma");
#endif
#if WITH_ETHERTRANS
    if ((n = pthread_join (ss.ether_t, NULL)))
        errn_exit (n, "pthread_join _service_loop_ether");
#endif

    diod_fini (ss.srv);
    np_srv_destroy (ss.srv);
}
コード例 #13
0
ファイル: utils.c プロジェクト: Azendale/lxc
/*
 * Sets the process title to the specified title. Note:
 *   1. this function requires root to succeed
 *   2. it clears /proc/self/environ
 *   3. it may not succed (e.g. if title is longer than /proc/self/environ +
 *      the original title)
 */
int setproctitle(char *title)
{
	char buf[2048], *tmp;
	FILE *f;
	int i, len, ret = 0;
	unsigned long arg_start, arg_end, env_start, env_end;

	f = fopen_cloexec("/proc/self/stat", "r");
	if (!f) {
		return -1;
	}

	tmp = fgets(buf, sizeof(buf), f);
	fclose(f);
	if (!tmp) {
		return -1;
	}

	/* Skip the first 47 fields, column 48-51 are ARG_START and
	 * ARG_END. */
	tmp = strchr(buf, ' ');
	for (i = 0; i < 46; i++) {
		if (!tmp)
			return -1;
		tmp = strchr(tmp+1, ' ');
	}

	if (!tmp)
		return -1;

	i = sscanf(tmp, "%lu %lu %lu %lu", &arg_start, &arg_end, &env_start, &env_end);
	if (i != 4) {
		return -1;
	}

	/* Include the null byte here, because in the calculations below we
	 * want to have room for it. */
	len = strlen(title) + 1;

	/* We're truncating the environment, so we should use at most the
	 * length of the argument + environment for the title. */
	if (len > env_end - arg_start) {
		arg_end = env_end;
		len = env_end - arg_start;
	} else {
		/* Only truncate the environment if we're actually going to
		 * overwrite part of it. */
		if (len >= arg_end - arg_start) {
			env_start = env_end;
		}

		arg_end = arg_start + len;

		/* check overflow */
		if (arg_end < len || arg_end < arg_start) {
			return -1;
		}

	}

	strcpy((char*)arg_start, title);

	ret |= prctl(PR_SET_MM, PR_SET_MM_ARG_START,   arg_start, 0, 0);
	ret |= prctl(PR_SET_MM, PR_SET_MM_ARG_END,     arg_end, 0, 0);
	ret |= prctl(PR_SET_MM, PR_SET_MM_ENV_START,   env_start, 0, 0);
	ret |= prctl(PR_SET_MM, PR_SET_MM_ENV_END,     env_end, 0, 0);

	return ret;
}
コード例 #14
0
ファイル: client.c プロジェクト: pzl/statbar
static void spawn_bar(int *lemon_in, int *lemon_out, const char *geometry) {
	int child_in[2]; //could be done one 2D array, fd[2][2], but harder to read
	int child_out[2];
	pid_t childpid;

	pipe(child_in);
	pipe(child_out);

	if ((childpid = fork()) == -1) {
		perror("fork");
		exit(-1);
	}

	if (childpid == 0) {
		//child
		if (close(child_in[1]) < 0){ //close input of first pipe
			perror("closing child input");
		}
		if (close(child_out[0]) < 0){ //close output of second pipe
			perror("closing child output");
		}

		//send SIGHUP to us when parent dies
		if (prctl(PR_SET_PDEATHSIG, SIGHUP) < 0){ //Linux only
			perror("setting up deathsig");
		}

		if (dup2(child_in[0],STDIN_FILENO) < 0){ //replace lemon stdin with pipe output
			perror("setting lemon stdin");
		}
		if (dup2(child_out[1],STDOUT_FILENO) < 0){ //send lemon output through pipe2 input
			perror("setting lemon stdout");
		}

		signal(SIGUSR1,SIG_IGN);

		//if pgrep -x compton; then #ee383a3b else #383a3b fi

		execlp("lemonbar", "lemonbar",
		       "-g",geometry,"-B","#ee383a3b","-F","#ffffff",
		       "-u","3","-a","20",
		       "-f","-*-terminus-medium-*-*-*-12-*-*-*-*-*-iso10646-*",
		       "-f","-*-lemon-medium-*-*-*-10-*-75-75-*-*-iso10646-*",
		       "-f","-*-uushi-*-*-*-*-*-*-75-75-*-*-iso10646-*",
		       "-f","-*-siji-*-*-*-*-10-*-75-75-*-*-iso10646-*",
		       NULL);
		exit(0); //if lemonbar exits, don't continue running C code. DIE!
	} else {
		//parent
		if (close(child_in[0]) < 0){ //close output of child's stdin
			perror("parent closing output");
		}
		if (close(child_out[1]) <0){ //close input of its stdout
			perror("parent closing intput");
		}

		*lemon_in = child_in[1]; //child_in[1] is stdin to lemonbar
		*lemon_out = child_out[0]; //child_out[0] is lemonbar output
		DEBUG_(printf("waiting for lemonbar to start up\n"));
		sleep(1); //give time for lemonbar to start, pipes to be swapped
		DEBUG_(printf("spawned lemonbar\n"));
	}
}
コード例 #15
0
ファイル: ngx_process_cycle.c プロジェクト: chengpan/test
static void
ngx_worker_process_init(ngx_cycle_t *cycle, ngx_int_t worker)
{
    sigset_t          set;
    uint64_t          cpu_affinity;
    ngx_int_t         n;
    ngx_uint_t        i;
    struct rlimit     rlmt;
    ngx_core_conf_t  *ccf;
    ngx_listening_t  *ls;

    if (ngx_set_environment(cycle, NULL) == NULL) {
        /* fatal */
        exit(2);
    }

    ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);

    if (worker >= 0 && ccf->priority != 0) {
        if (setpriority(PRIO_PROCESS, 0, ccf->priority) == -1) {
            ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                          "setpriority(%d) failed", ccf->priority);
        }
    }

    if (ccf->rlimit_nofile != NGX_CONF_UNSET) {
        rlmt.rlim_cur = (rlim_t) ccf->rlimit_nofile;
        rlmt.rlim_max = (rlim_t) ccf->rlimit_nofile;

        if (setrlimit(RLIMIT_NOFILE, &rlmt) == -1) {
            ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                          "setrlimit(RLIMIT_NOFILE, %i) failed",
                          ccf->rlimit_nofile);
        }
    }

    if (ccf->rlimit_core != NGX_CONF_UNSET) {
        rlmt.rlim_cur = (rlim_t) ccf->rlimit_core;
        rlmt.rlim_max = (rlim_t) ccf->rlimit_core;

        if (setrlimit(RLIMIT_CORE, &rlmt) == -1) {
            ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                          "setrlimit(RLIMIT_CORE, %O) failed",
                          ccf->rlimit_core);
        }
    }

    if (geteuid() == 0) {
        if (setgid(ccf->group) == -1) {
            ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
                          "setgid(%d) failed", ccf->group);
            /* fatal */
            exit(2);
        }

        if (initgroups(ccf->username, ccf->group) == -1) {
            ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
                          "initgroups(%s, %d) failed",
                          ccf->username, ccf->group);
        }

        if (setuid(ccf->user) == -1) {
            ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
                          "setuid(%d) failed", ccf->user);
            /* fatal */
            exit(2);
        }
    }

    if (worker >= 0) {
        cpu_affinity = ngx_get_cpu_affinity(worker);

        if (cpu_affinity) {
            ngx_setaffinity(cpu_affinity, cycle->log);
        }
    }

#if (NGX_HAVE_PR_SET_DUMPABLE)

    /* allow coredump after setuid() in Linux 2.4.x */

    if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) == -1) {
        ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                      "prctl(PR_SET_DUMPABLE) failed");
    }

#endif

    if (ccf->working_directory.len) {
        if (chdir((char *) ccf->working_directory.data) == -1) {
            ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                          "chdir(\"%s\") failed", ccf->working_directory.data);
            /* fatal */
            exit(2);
        }
    }

    sigemptyset(&set);

    if (sigprocmask(SIG_SETMASK, &set, NULL) == -1) {
        ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                      "sigprocmask() failed");
    }

    srandom((ngx_pid << 16) ^ ngx_time());

    /*
     * disable deleting previous events for the listening sockets because
     * in the worker processes there are no events at all at this point
     */
    ls = cycle->listening.elts;
    for (i = 0; i < cycle->listening.nelts; i++) {
        ls[i].previous = NULL;
    }

    for (i = 0; ngx_modules[i]; i++) {
        if (ngx_modules[i]->init_process) {
            if (ngx_modules[i]->init_process(cycle) == NGX_ERROR) {
                /* fatal */
                exit(2);
            }
        }
    }

    for (n = 0; n < ngx_last_process; n++) {

        if (ngx_processes[n].pid == -1) {
            continue;
        }

        if (n == ngx_process_slot) {
            continue;
        }

        if (ngx_processes[n].channel[1] == -1) {
            continue;
        }

        if (close(ngx_processes[n].channel[1]) == -1) {
            ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                          "close() channel failed");
        }
    }

    if (close(ngx_processes[ngx_process_slot].channel[0]) == -1) {
        ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                      "close() channel failed");
    }

#if 0
    ngx_last_process = 0;
#endif

    if (ngx_add_channel_event(cycle, ngx_channel, NGX_READ_EVENT,
                              ngx_channel_handler)
        == NGX_ERROR)
    {
        /* fatal */
        exit(2);
    }
}
コード例 #16
0
ファイル: main.c プロジェクト: joselzinga/tvheadend-hdhomerun
int
main(int argc, char **argv)
{
  int i;
  sigset_t set;
#if ENABLE_MPEGTS
  uint32_t adapter_mask = 0;
#endif
  int  log_level   = LOG_INFO;
  int  log_options = TVHLOG_OPT_MILLIS | TVHLOG_OPT_STDERR | TVHLOG_OPT_SYSLOG;
  const char *log_debug = NULL, *log_trace = NULL;
  char buf[512];

  main_tid = pthread_self();

  /* Setup global mutexes */
  pthread_mutex_init(&ffmpeg_lock, NULL);
  pthread_mutex_init(&fork_lock, NULL);
  pthread_mutex_init(&global_lock, NULL);
  pthread_mutex_init(&atomic_lock, NULL);
  pthread_cond_init(&gtimer_cond, NULL);

  /* Defaults */
  tvheadend_webui_port      = 9981;
  tvheadend_webroot         = NULL;
  tvheadend_htsp_port       = 9982;
  tvheadend_htsp_port_extra = 0;

  /* Command line options */
  int         opt_help         = 0,
              opt_version      = 0,
              opt_fork         = 0,
              opt_firstrun     = 0,
              opt_stderr       = 0,
              opt_syslog       = 0,
              opt_uidebug      = 0,
              opt_abort        = 0,
              opt_noacl        = 0,
              opt_fileline     = 0,
              opt_threadid     = 0,
              opt_ipv6         = 0,
              opt_tsfile_tuner = 0,
              opt_dump         = 0,
              opt_xspf         = 0;
  const char *opt_config       = NULL,
             *opt_user         = NULL,
             *opt_group        = NULL,
             *opt_logpath      = NULL,
             *opt_log_debug    = NULL,
             *opt_log_trace    = NULL,
             *opt_pidpath      = "/var/run/tvheadend.pid",
#if ENABLE_LINUXDVB
             *opt_dvb_adapters = NULL,
#endif
             *opt_bindaddr     = NULL,
             *opt_subscribe    = NULL,
             *opt_user_agent   = NULL;
  str_list_t  opt_satip_xml    = { .max = 10, .num = 0, .str = calloc(10, sizeof(char*)) };
  str_list_t  opt_tsfile       = { .max = 10, .num = 0, .str = calloc(10, sizeof(char*)) };
  cmdline_opt_t cmdline_opts[] = {
    {   0, NULL,        "Generic Options",         OPT_BOOL, NULL         },
    { 'h', "help",      "Show this page",          OPT_BOOL, &opt_help    },
    { 'v', "version",   "Show version infomation", OPT_BOOL, &opt_version },

    {   0, NULL,        "Service Configuration",   OPT_BOOL, NULL         },
    { 'c', "config",    "Alternate config path",   OPT_STR,  &opt_config  },
    { 'f', "fork",      "Fork and run as daemon",  OPT_BOOL, &opt_fork    },
    { 'u', "user",      "Run as user",             OPT_STR,  &opt_user    },
    { 'g', "group",     "Run as group",            OPT_STR,  &opt_group   },
    { 'p', "pid",       "Alternate pid path",      OPT_STR,  &opt_pidpath },
    { 'C', "firstrun",  "If no user account exists then create one with\n"
	                      "no username and no password. Use with care as\n"
	                      "it will allow world-wide administrative access\n"
	                      "to your Tvheadend installation until you edit\n"
	                      "the access-control from within the Tvheadend UI",
      OPT_BOOL, &opt_firstrun },
#if ENABLE_LINUXDVB
    { 'a', "adapters",  "Only use specified DVB adapters (comma separated)",
      OPT_STR, &opt_dvb_adapters },
#endif
#if ENABLE_SATIP_CLIENT
    {   0, "satip_xml", "URL with the SAT>IP server XML location",
      OPT_STR_LIST, &opt_satip_xml },
#endif
    {   0, NULL,         "Server Connectivity",    OPT_BOOL, NULL         },
    { '6', "ipv6",       "Listen on IPv6",         OPT_BOOL, &opt_ipv6    },
    { 'b', "bindaddr",   "Specify bind address",   OPT_STR,  &opt_bindaddr},
    {   0, "http_port",  "Specify alternative http port",
      OPT_INT, &tvheadend_webui_port },
    {   0, "http_root",  "Specify alternative http webroot",
      OPT_STR, &tvheadend_webroot },
    {   0, "htsp_port",  "Specify alternative htsp port",
      OPT_INT, &tvheadend_htsp_port },
    {   0, "htsp_port2", "Specify extra htsp port",
      OPT_INT, &tvheadend_htsp_port_extra },
    {   0, "useragent",  "Specify User-Agent header for the http client",
      OPT_STR, &opt_user_agent },
    {   0, "xspf",       "Use xspf playlist instead M3U",
      OPT_BOOL, &opt_xspf },

    {   0, NULL,        "Debug Options",           OPT_BOOL, NULL         },
    { 'd', "stderr",    "Enable debug on stderr",  OPT_BOOL, &opt_stderr  },
    { 's', "syslog",    "Enable debug to syslog",  OPT_BOOL, &opt_syslog  },
    { 'l', "logfile",   "Enable debug to file",    OPT_STR,  &opt_logpath },
    {   0, "debug",     "Enable debug subsystems", OPT_STR,  &opt_log_debug },
#if ENABLE_TRACE
    {   0, "trace",     "Enable trace subsystems", OPT_STR,  &opt_log_trace },
#endif
    {   0, "fileline",  "Add file and line numbers to debug", OPT_BOOL, &opt_fileline },
    {   0, "threadid",  "Add the thread ID to debug", OPT_BOOL, &opt_threadid },
    {   0, "uidebug",   "Enable webUI debug (non-minified JS)", OPT_BOOL, &opt_uidebug },
    { 'A', "abort",     "Immediately abort",       OPT_BOOL, &opt_abort   },
    { 'D', "dump",      "Enable coredumps for daemon", OPT_BOOL, &opt_dump },
    {   0, "noacl",     "Disable all access control checks",
      OPT_BOOL, &opt_noacl },
    { 'j', "join",      "Subscribe to a service permanently",
      OPT_STR, &opt_subscribe },


    { 0, NULL, "TODO: testing", OPT_BOOL, NULL },
    { 0, "tsfile_tuners", "Number of tsfile tuners", OPT_INT, &opt_tsfile_tuner },
    { 0, "tsfile", "tsfile input (mux file)", OPT_STR_LIST, &opt_tsfile },

  };

  /* Get current directory */
  tvheadend_cwd = dirname(dirname(tvh_strdupa(argv[0])));

  /* Set locale */
  setlocale(LC_ALL, "");
  setlocale(LC_NUMERIC, "C");

  /* make sure the timezone is set */
  tzset();

  /* Process command line */
  for (i = 1; i < argc; i++) {

    /* Find option */
    cmdline_opt_t *opt
      = cmdline_opt_find(cmdline_opts, ARRAY_SIZE(cmdline_opts), argv[i]);
    if (!opt)
      show_usage(argv[0], cmdline_opts, ARRAY_SIZE(cmdline_opts),
                 "invalid option specified [%s]", argv[i]);

    /* Process */
    if (opt->type == OPT_BOOL)
      *((int*)opt->param) = 1;
    else if (++i == argc)
      show_usage(argv[0], cmdline_opts, ARRAY_SIZE(cmdline_opts),
                 "option %s requires a value", opt->lopt);
    else if (opt->type == OPT_INT)
      *((int*)opt->param) = atoi(argv[i]);
    else if (opt->type == OPT_STR_LIST) {
      str_list_t *strl = opt->param;
      if (strl->num < strl->max)
        strl->str[strl->num++] = argv[i];
    }
    else
      *((char**)opt->param) = argv[i];

    /* Stop processing */
    if (opt_help)
      show_usage(argv[0], cmdline_opts, ARRAY_SIZE(cmdline_opts), NULL);
    if (opt_version)
      show_version(argv[0]);
  }

  /* Additional cmdline processing */
#if ENABLE_LINUXDVB
  if (!opt_dvb_adapters) {
    adapter_mask = ~0;
  } else {
    char *p, *e;
    char *r = NULL;
    char *dvb_adapters = strdup(opt_dvb_adapters);
    adapter_mask = 0x0;
    p = strtok_r(dvb_adapters, ",", &r);
    while (p) {
      int a = strtol(p, &e, 10);
      if (*e != 0 || a < 0 || a > 31) {
        tvhlog(LOG_ERR, "START", "Invalid adapter number '%s'", p);
        free(dvb_adapters);
        return 1;
      }
      adapter_mask |= (1 << a);
      p = strtok_r(NULL, ",", &r);
    }
    free(dvb_adapters);
    if (!adapter_mask) {
      tvhlog(LOG_ERR, "START", "No adapters specified!");
      return 1;
    }
  }
#endif
  if (tvheadend_webroot) {
    char *tmp;
    if (*tvheadend_webroot == '/')
      tmp = strdup(tvheadend_webroot);
    else {
      tmp = malloc(strlen(tvheadend_webroot)+2);
      *tmp = '/';
      strcpy(tmp+1, tvheadend_webroot);
    }
    if (tmp[strlen(tmp)-1] == '/')
      tmp[strlen(tmp)-1] = '\0';
    tvheadend_webroot = tmp;
  }
  tvheadend_webui_debug = opt_uidebug;

  /* Setup logging */
  if (isatty(2))
    log_options |= TVHLOG_OPT_DECORATE;
  if (opt_stderr || opt_syslog || opt_logpath) {
    if (!opt_log_trace && !opt_log_debug)
      log_debug      = "all";
    log_level      = LOG_DEBUG;
    if (opt_stderr)
      log_options   |= TVHLOG_OPT_DBG_STDERR;
    if (opt_syslog)
      log_options   |= TVHLOG_OPT_DBG_SYSLOG;
    if (opt_logpath)
      log_options   |= TVHLOG_OPT_DBG_FILE;
  }
  if (opt_fileline)
    log_options |= TVHLOG_OPT_FILELINE;
  if (opt_threadid)
    log_options |= TVHLOG_OPT_THREAD;
  if (opt_log_trace) {
    log_level  = LOG_TRACE;
    log_trace  = opt_log_trace;
  }
  if (opt_log_debug)
    log_debug  = opt_log_debug;
    
  tvhlog_init(log_level, log_options, opt_logpath);
  tvhlog_set_debug(log_debug);
  tvhlog_set_trace(log_trace);
 
  signal(SIGPIPE, handle_sigpipe); // will be redundant later

  /* Daemonise */
  if(opt_fork) {
    const char *homedir;
    gid_t gid;
    uid_t uid;
    struct group  *grp = getgrnam(opt_group ?: "video");
    struct passwd *pw  = opt_user ? getpwnam(opt_user) : NULL;
    FILE   *pidfile    = fopen(opt_pidpath, "w+");

    if(grp != NULL) {
      gid = grp->gr_gid;
    } else {
      gid = 1;
    }

    if (pw != NULL) {
      if (getuid() != pw->pw_uid) {
        gid_t glist[10];
        int gnum;
        gnum = get_user_groups(pw, glist, 10);
        if (setgroups(gnum, glist)) {
          tvhlog(LOG_ALERT, "START",
                 "setgroups() failed, do you have permission?");
          return 1;
        }
      }
      uid     = pw->pw_uid;
      homedir = pw->pw_dir;
      setenv("HOME", homedir, 1);
    } else {
      uid = 1;
    }
    if ((getgid() != gid) && setgid(gid)) {
      tvhlog(LOG_ALERT, "START",
             "setgid() failed, do you have permission?");
      return 1;
    }
    if ((getuid() != uid) && setuid(uid)) {
      tvhlog(LOG_ALERT, "START",
             "setuid() failed, do you have permission?");
      return 1;
    }

    if(daemon(0, 0)) {
      exit(2);
    }
    if(pidfile != NULL) {
      fprintf(pidfile, "%d\n", getpid());
      fclose(pidfile);
    }

    /* Make dumpable */
    if (opt_dump) {
#ifdef PLATFORM_LINUX
      if (chdir("/tmp"))
        tvhwarn("START", "failed to change cwd to /tmp");
      prctl(PR_SET_DUMPABLE, 1);
#else
      tvhwarn("START", "Coredumps not implemented on your platform");
#endif
    }

    umask(0);
  }

  tvheadend_running = 1;

  /* Start log thread (must be done post fork) */
  tvhlog_start();

  /* Alter logging */
  if (opt_fork)
    tvhlog_options &= ~TVHLOG_OPT_STDERR;
  if (!isatty(2))
    tvhlog_options &= ~TVHLOG_OPT_DECORATE;
  
  /* Initialise clock */
  pthread_mutex_lock(&global_lock);
  time(&dispatch_clock);

  /* Signal handling */
  sigfillset(&set);
  sigprocmask(SIG_BLOCK, &set, NULL);
  trap_init(argv[0]);

  /* SSL library init */
  OPENSSL_config(NULL);
  SSL_load_error_strings();
  SSL_library_init();
  
  /* Initialise configuration */
  uuid_init();
  idnode_init();
  config_init(opt_config);

  /**
   * Initialize subsystems
   */

  intlconv_init();
  
  api_init();

  fsmonitor_init();

#if ENABLE_LIBAV
  libav_init();
  transcoding_init();
#endif

  imagecache_init();

  http_client_init(opt_user_agent);
  esfilter_init();

  service_init();

#if ENABLE_MPEGTS
  mpegts_init(adapter_mask, &opt_satip_xml, &opt_tsfile, opt_tsfile_tuner);
#endif

  channel_init();

  subscription_init();

  access_init(opt_firstrun, opt_noacl);

#if ENABLE_TIMESHIFT
  timeshift_init();
#endif

  tcp_server_init(opt_ipv6);
  http_server_init(opt_bindaddr);
  webui_init(opt_xspf);
#if ENABLE_UPNP
  upnp_server_init(opt_bindaddr);
#endif

  service_mapper_init();

  descrambler_init();

  epggrab_init();
  epg_init();

  dvr_init();

  htsp_init(opt_bindaddr);


  if(opt_subscribe != NULL)
    subscription_dummy_join(opt_subscribe, 1);

  avahi_init();
  bonjour_init();

  epg_updated(); // cleanup now all prev ref's should have been created

  pthread_mutex_unlock(&global_lock);

  /**
   * Wait for SIGTERM / SIGINT, but only in this thread
   */

  sigemptyset(&set);
  sigaddset(&set, SIGTERM);
  sigaddset(&set, SIGINT);

  signal(SIGTERM, doexit);
  signal(SIGINT, doexit);

  pthread_sigmask(SIG_UNBLOCK, &set, NULL);

  tvhlog(LOG_NOTICE, "START", "HTS Tvheadend version %s started, "
         "running as PID:%d UID:%d GID:%d, CWD:%s CNF:%s",
         tvheadend_version,
         getpid(), getuid(), getgid(), getcwd(buf, sizeof(buf)),
         hts_settings_get_root());

  if(opt_abort)
    abort();

  mainloop();

#if ENABLE_UPNP
  tvhftrace("main", upnp_server_done);
#endif
  tvhftrace("main", htsp_done);
  tvhftrace("main", http_server_done);
  tvhftrace("main", webui_done);
  tvhftrace("main", fsmonitor_done);
#if ENABLE_MPEGTS
  tvhftrace("main", mpegts_done);
#endif
  tvhftrace("main", http_client_done);

  // Note: the locking is obviously a bit redundant, but without
  //       we need to disable the gtimer_arm call in epg_save()
  pthread_mutex_lock(&global_lock);
  tvhftrace("main", epg_save);

#if ENABLE_TIMESHIFT
  tvhftrace("main", timeshift_term);
#endif
  pthread_mutex_unlock(&global_lock);

  tvhftrace("main", epggrab_done);
  tvhftrace("main", tcp_server_done);
  tvhftrace("main", descrambler_done);
  tvhftrace("main", service_mapper_done);
  tvhftrace("main", service_done);
  tvhftrace("main", channel_done);
  tvhftrace("main", dvr_done);
  tvhftrace("main", subscription_done);
  tvhftrace("main", access_done);
  tvhftrace("main", epg_done);
  tvhftrace("main", avahi_done);
  tvhftrace("main", bonjour_done);
  tvhftrace("main", imagecache_done);
  tvhftrace("main", idnode_done);
  tvhftrace("main", lang_code_done);
  tvhftrace("main", api_done);
  tvhftrace("main", config_done);
  tvhftrace("main", hts_settings_done);
  tvhftrace("main", dvb_done);
  tvhftrace("main", lang_str_done);
  tvhftrace("main", esfilter_done);
  tvhftrace("main", intlconv_done);
  tvhftrace("main", urlparse_done);

  tvhlog(LOG_NOTICE, "STOP", "Exiting HTS Tvheadend");
  tvhlog_end();

  if(opt_fork)
    unlink(opt_pidpath);
    
  free(opt_tsfile.str);
  free(opt_satip_xml.str);

  /* OpenSSL - welcome to the "cleanup" hell */
  ENGINE_cleanup();
  RAND_cleanup();
  CRYPTO_cleanup_all_ex_data();
  EVP_cleanup();
  CONF_modules_free();
  COMP_zlib_cleanup();
  ERR_remove_state(0);
  ERR_free_strings();
  {
    sk_SSL_COMP_free(SSL_COMP_get_compression_methods());
  }
  /* end of OpenSSL cleanup code */

  return 0;
}

/**
 *
 */
void
tvh_str_set(char **strp, const char *src)
{
  free(*strp);
  *strp = src ? strdup(src) : NULL;
}


/**
 *
 */
int
tvh_str_update(char **strp, const char *src)
{
  if(src == NULL)
    return 0;
  free(*strp);
  *strp = strdup(src);
  return 1;
}


/**
 *
 */
void
scopedunlock(pthread_mutex_t **mtxp)
{
  pthread_mutex_unlock(*mtxp);
}
コード例 #17
0
ファイル: util.hpp プロジェクト: dforsi/libosmium
 inline void set_thread_name(const char* name) noexcept {
     prctl(PR_SET_NAME, name, 0, 0, 0);
 }
コード例 #18
0
static void start(void *obj, int cam_num, void *display, void *context, void *cam_texture, int egl_image_num) {
	opus_capture *_this = (opus_capture*) obj;
	pid_t pid = 0;
	int pin_fd[2];
	int pout_fd[2];

	pipe(pin_fd);
	pipe(pout_fd);
	pid = fork();
	if (pid == 0) {
		const int MAX_ARGC = 128;
		int argc = 0;
		char **argv = malloc(MAX_ARGC * sizeof(char*));
		argv[argc++] = "ffmpeg";
		argv[argc++] = "-v";
		argv[argc++] = "quiet";
		argv[argc++] = "-f";
		argv[argc++] = "alsa";
		argv[argc++] = "-i";
		argv[argc++] = "hw:1,0";
		argv[argc++] = "-strict";
		argv[argc++] = "-2";
		argv[argc++] = "-b:a";
		argv[argc++] = "64k";
		argv[argc++] = "-opus_delay";
		argv[argc++] = "20";

		//output
		argv[argc++] = "-f";
		argv[argc++] = "opus";
		argv[argc++] = "pipe:1";
		argv[argc++] = NULL;

		// Child
		dup2(pin_fd[R], STDIN_FILENO);
		dup2(pout_fd[W], STDOUT_FILENO);
		//dup2(pout_fd[W], STDERR_FILENO);

#if __linux
		//ask kernel to deliver SIGTERM in case the parent dies
		prctl(PR_SET_PDEATHSIG, SIGTERM);
#endif

		execvp("ffmpeg", argv);
		// Nothing below _this line should be executed by child process. If so,
		// it means that the execl function wasn't successfull, so lets exit:
		exit(1);
	}
// The code below will be executed only by parent. You can write and read
// from the child using pipefd descriptors, and you can send signals to
// the process using its pid by kill() function. If the child process will
// exit unexpectedly, the parent process will obtain SIGCHLD signal that
// can be handled (e.g. you can respawn the child process).

//close unused pipe ends
	close(pin_fd[R]);
	close(pout_fd[W]);

	pthread_mutex_init(&_this->frame_data_queue_mutex, 0);
	pthread_create(&_this->pout_thread, NULL, pout_thread_func, (void*) _this);

	_this->pid = pid;
	_this->pin_fd = pin_fd[W];
	_this->pout_fd = pout_fd[R];
}
コード例 #19
0
void ExternalSource::run() {
	int pipefd[2];

	prctl(PR_SET_NAME, (unsigned long)&"gatord-external", 0, 0, 0);

	if (pipe_cloexec(pipefd) != 0) {
		logg->logError(__FILE__, __LINE__, "pipe failed");
		handleException();
	}
	mInterruptFd = pipefd[1];

	if (!mMonitor.add(pipefd[0])) {
		logg->logError(__FILE__, __LINE__, "Monitor::add failed");
		handleException();
	}

	// Notify annotate clients to retry connecting to gatord
	gSessionData->annotateListener.signal();

	while (gSessionData->mSessionIsActive) {
		struct epoll_event events[16];
		// Clear any pending sem posts
		while (sem_trywait(&mBufferSem) == 0);
		int ready = mMonitor.wait(events, ARRAY_LENGTH(events), -1);
		if (ready < 0) {
			logg->logError(__FILE__, __LINE__, "Monitor::wait failed");
			handleException();
		}

		const uint64_t currTime = getTime();

		for (int i = 0; i < ready; ++i) {
			const int fd = events[i].data.fd;
			if (fd == mMveStartupUds.getFd()) {
				// Mali Video Engine says it's alive
				int client = mMveStartupUds.acceptConnection();
				// Don't read from this connection, establish a new connection to Mali-V500
				close(client);
				if (!connectMve()) {
					logg->logError(__FILE__, __LINE__, "Unable to configure incoming Mali video connection");
					handleException();
				}
			} else if (fd == mMaliStartupUds.getFd()) {
				// Mali Graphics says it's alive
				int client = mMaliStartupUds.acceptConnection();
				// Don't read from this connection, establish a new connection to Mali Graphics
				close(client);
				if (!connectMali()) {
					logg->logError(__FILE__, __LINE__, "Unable to configure incoming Mali graphics connection");
					handleException();
				}
			} else if (fd == mAnnotate.getFd()) {
				int client = mAnnotate.acceptConnection();
				if (!setNonblock(client) || !mMonitor.add(client)) {
					logg->logError(__FILE__, __LINE__, "Unable to set socket options on incoming annotation connection");
					handleException();
				}
			} else if (fd == pipefd[0]) {
				// Means interrupt has been called and mSessionIsActive should be reread
			} else {
				/* This can result in some starvation if there are multiple
				 * threads which are annotating heavily, but it is not
				 * recommended that threads annotate that much as it can also
				 * starve out the gator data.
				 */
				while (gSessionData->mSessionIsActive) {
					// Wait until there is enough room for the fd, two headers and two ints
					waitFor(7*Buffer::MAXSIZE_PACK32 + 2*sizeof(uint32_t));
					mBuffer.packInt(fd);
					const int contiguous = mBuffer.contiguousSpaceAvailable();
					const int bytes = read(fd, mBuffer.getWritePos(), contiguous);
					if (bytes < 0) {
						if (errno == EAGAIN) {
							// Nothing left to read
							mBuffer.commit(currTime);
							break;
						}
						// Something else failed, close the socket
						mBuffer.commit(currTime);
						mBuffer.packInt(-1);
						mBuffer.packInt(fd);
						mBuffer.commit(currTime);
						close(fd);
						break;
					} else if (bytes == 0) {
						// The other side is closed
						mBuffer.commit(currTime);
						mBuffer.packInt(-1);
						mBuffer.packInt(fd);
						mBuffer.commit(currTime);
						close(fd);
						break;
					}

					mBuffer.advanceWrite(bytes);
					mBuffer.commit(currTime);

					// Short reads also mean nothing is left to read
					if (bytes < contiguous) {
						break;
					}
				}
			}
		}
	}

	mBuffer.setDone();

	if (mMveUds >= 0) {
		gSessionData->maliVideo.stop(mMveUds);
	}

	mInterruptFd = -1;
	close(pipefd[0]);
	close(pipefd[1]);
}
コード例 #20
0
/*工作进程初始化*/
static void
ngx_worker_process_init(ngx_cycle_t *cycle, ngx_uint_t priority)
{
    sigset_t          set;
    ngx_int_t         n;
    ngx_uint_t        i;
    struct rlimit     rlmt;
    ngx_core_conf_t  *ccf;
    ngx_listening_t  *ls;
	// 设置nginx服务器的运行环境
    if (ngx_set_environment(cycle, NULL) == NULL) {
        /* fatal */
        exit(2);
    }
	//获取配置的上下文
    ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);

    if (priority && ccf->priority != 0) {
        if (setpriority(PRIO_PROCESS, 0, ccf->priority) == -1) { // 设置工作进程优先级
            ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, //出错处理
                          "setpriority(%d) failed", ccf->priority);
        }
    }

    if (ccf->rlimit_nofile != NGX_CONF_UNSET) {
        rlmt.rlim_cur = (rlim_t) ccf->rlimit_nofile;       // 获取配置信息
        rlmt.rlim_max = (rlim_t) ccf->rlimit_nofile;

        if (setrlimit(RLIMIT_NOFILE, &rlmt) == -1) {		//设置打开文件描述符的上限
            ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                          "setrlimit(RLIMIT_NOFILE, %i) failed",
                          ccf->rlimit_nofile);
        }
    }

    if (ccf->rlimit_core != NGX_CONF_UNSET) {
        rlmt.rlim_cur = (rlim_t) ccf->rlimit_core;
        rlmt.rlim_max = (rlim_t) ccf->rlimit_core;

        if (setrlimit(RLIMIT_CORE, &rlmt) == -1) {          // 设置内核转储文件的最大长度
            ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                          "setrlimit(RLIMIT_CORE, %O) failed",
                          ccf->rlimit_core);
        }
    }

#ifdef RLIMIT_SIGPENDING
    if (ccf->rlimit_sigpending != NGX_CONF_UNSET) {
        rlmt.rlim_cur = (rlim_t) ccf->rlimit_sigpending;
        rlmt.rlim_max = (rlim_t) ccf->rlimit_sigpending;

        if (setrlimit(RLIMIT_SIGPENDING, &rlmt) == -1) {
            ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                          "setrlimit(RLIMIT_SIGPENDING, %i) failed",
                          ccf->rlimit_sigpending);
        }
    }
#endif

    if (geteuid() == 0) {
        if (setgid(ccf->group) == -1) {      //设置组ID
            ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
                          "setgid(%d) failed", ccf->group);
            /* fatal */
            exit(2);
        }

        if (initgroups(ccf->username, ccf->group) == -1) {    // 初始化组清单
            ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
                          "initgroups(%s, %d) failed",
                          ccf->username, ccf->group);
        }

        if (setuid(ccf->user) == -1) {  // 设置用户ID
            ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
                          "setuid(%d) failed", ccf->user);
            /* fatal */
            exit(2);
        }
    }

#if (NGX_HAVE_SCHED_SETAFFINITY)

    if (cpu_affinity) {
        ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0,
                      "sched_setaffinity(0x%08Xl)", cpu_affinity);

        if (sched_setaffinity(0, sizeof(cpu_affinity),
                              (cpu_set_t *) &cpu_affinity)
            == -1)
        {
            ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                          "sched_setaffinity(0x%08Xl) failed", cpu_affinity);
        }
    }

#endif

#if (NGX_HAVE_PR_SET_DUMPABLE)

    /* allow coredump after setuid() in Linux 2.4.x */

    if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) == -1) {
        ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                      "prctl(PR_SET_DUMPABLE) failed");
    }

#endif

    if (ccf->working_directory.len) {
        if (chdir((char *) ccf->working_directory.data) == -1) {    //设置进程的工作目录
            ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                          "chdir(\"%s\") failed", ccf->working_directory.data);
            /* fatal */
            exit(2);
        }
    }

    sigemptyset(&set);

    if (sigprocmask(SIG_SETMASK, &set, NULL) == -1) {           // 取消最信号的屏蔽
        ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                      "sigprocmask() failed");
    }

    /*
     * disable deleting previous events for the listening sockets because
     * in the worker processes there are no events at all at this point
     */
    ls = cycle->listening.elts;
    for (i = 0; i < cycle->listening.nelts; i++) {
        ls[i].previous = NULL;  // 遍历并设置所有监听套接字的状态
    }
	// 初始化nginx各个模块
    for (i = 0; ngx_modules[i]; i++) {
        if (ngx_modules[i]->init_process) { 
            //进程初始化, 调用每个模块的init_process,用它做模块开发的时候,使用得挺少的 
            //这里要特别看的是event模块:
            //nginx的event模块包含一个init_process,也就是ngx_event_process_init(ngx_event.c).
            //这个函数就是nginx的驱动器,他初始化事件驱动器,连接池,定时器,以及挂在listen 句柄的回调函数
            if (ngx_modules[i]->init_process(cycle) == NGX_ERROR) {
                /* fatal */
                exit(2);
            }
        }
    }
    // 这里循环用户关闭其他worker进程的无用channel资源
    for (n = 0; n < ngx_last_process; n++) {

        if (ngx_processes[n].pid == -1) { //n位置的进程不存在,这里是预防性的代码
            continue;
        }
        //ngx_process_slot是创建worker进程的时候,从master进程复制过来的,此处就是指本worker进程在数组中的索引位置
        if (n == ngx_process_slot) {  
            continue;
        }

        if (ngx_processes[n].channel[1] == -1) { // channel不存在,跳过
            continue;
        }
        // 创建worker进程时,会将master的资源复制过来,因此需要关闭无用的channel -- 其他worker进程的读端描述符
        if (close(ngx_processes[n].channel[1]) == -1) {
            ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                          "close() channel failed");
        }
    }
    // 关闭本worker进程的channel的写端描述符。
    if (close(ngx_processes[ngx_process_slot].channel[0]) == -1) {
        ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                      "close() channel failed");
    }

#if 0
    ngx_last_process = 0;
#endif
    // 将channel放入nginx关心的集合中,同时关注channel上的读事件。
	// 设置当前工作进程从channel[1]中监听事件
    if (ngx_add_channel_event(cycle, ngx_channel, NGX_READ_EVENT,
                              ngx_channel_handler)
        == NGX_ERROR)
    {
        /* fatal */
        exit(2);
    }
}
コード例 #21
0
static void start(void *obj, int cam_num, void *display, void *context, void *cam_texture, int egl_image_num) {
	ffmpeg_capture *_this = (ffmpeg_capture*) obj;
	pid_t pid = 0;
	int pin_fd[2];
	int pout_fd[2];
//	_this->callback = callback;
//	_this->user_data = user_data;
//	_this->width = width;
//	_this->height = height;
	_this->cam_num = cam_num;
	_this->glfw_window = (GLFWwindow*) display;
	_this->cam_texture = (GLuint*) cam_texture;

	pipe(pin_fd);
	pipe(pout_fd);
	pid = fork();
	if (pid == 0) {
		char size_str[16];
		char fps_str[16];

		const int MAX_ARGC = 128;
		int argc = 0;
		char **argv = malloc(MAX_ARGC * sizeof(char*));
		argv[argc++] = "ffmpeg";

		sprintf(size_str, "%dx%d", lg_width, lg_height);
		sprintf(fps_str, "%d", 15);

		if (strncmp(lg_options_input_type, "uvc", sizeof(lg_options_input_type)) == 0) {
#ifdef _WIN64
//define something for Windows (64-bit)
#elif _WIN32
//define something for Windows (32-bit)
#elif __APPLE__
#include "TargetConditionals.h"
#if TARGET_OS_IPHONE && TARGET_IPHONE_SIMULATOR
			// define something for simulator
#elif TARGET_OS_IPHONE
			// define something for iphone
#else
#define TARGET_OS_OSX 1
			// define something for OSX
			argv[argc++] = "-f";
			argv[argc++] = "avfoundation";
			argv[argc++] = "-pix_fmt";
			argv[argc++] = "uyvy422";
			argv[argc++] = "-framerate";
			argv[argc++] = fps_str;
			argv[argc++] = "-video_size";
			argv[argc++] = size_str;
			argv[argc++] = "-i";
			argv[argc++] = "0";
#endif
#elif __linux
// linux
			argv[argc++] = "-pix_fmt";
			argv[argc++] = "uyvy422";
			argv[argc++] = "-framerate";
			argv[argc++] = fps_str;
			argv[argc++] = "-video_size";
			argv[argc++] = size_str;
			argv[argc++] = "-i";
			argv[argc++] = "/dev/video0";
#elif __unix // all unices not caught above
// Unix
#elif __posix
// POSIX
#endif
		} else {
			argv[argc++] = "-video_size";
			argv[argc++] = size_str;
			argv[argc++] = "-c:v";
			argv[argc++] = lg_options_input_codec;
			argv[argc++] = "-i";
			argv[argc++] = "pipe:0";
		}

		//output
		argv[argc++] = "-r";
		argv[argc++] = fps_str;
		argv[argc++] = "-pix_fmt";
		argv[argc++] = "rgb24";
		argv[argc++] = "-f";
		argv[argc++] = "rawvideo";
		argv[argc++] = "pipe:1";
		argv[argc++] = NULL;

		// Child
		dup2(pin_fd[R], STDIN_FILENO);
		dup2(pout_fd[W], STDOUT_FILENO);
		//dup2(pout_fd[W], STDERR_FILENO);

#if __linux
		//ask kernel to deliver SIGTERM in case the parent dies
		prctl(PR_SET_PDEATHSIG, SIGTERM);
#endif

		execvp("ffmpeg", argv);
		// Nothing below _this line should be executed by child process. If so,
		// it means that the execl function wasn't successfull, so lets exit:
		exit(1);
	}
// The code below will be executed only by parent. You can write and read
// from the child using pipefd descriptors, and you can send signals to
// the process using its pid by kill() function. If the child process will
// exit unexpectedly, the parent process will obtain SIGCHLD signal that
// can be handled (e.g. you can respawn the child process).

//close unused pipe ends
	close(pin_fd[R]);
	close(pout_fd[W]);

	pthread_mutex_init(&_this->frame_data_queue_mutex, 0);
	pthread_create(&_this->pout_thread, NULL, pout_thread_func, (void*) _this);

	_this->pid = pid;
	_this->pin_fd = pin_fd[W];
	_this->pout_fd = pout_fd[R];
}
コード例 #22
0
ファイル: daemons.c プロジェクト: CommerceRack/uwsgi
void uwsgi_detach_daemons() {
	struct uwsgi_daemon *ud = uwsgi.daemons;
	while (ud) {
#ifdef UWSGI_SSL
		// stop any legion daemon, doesn't matter if dumb or smart
		if (ud->pid > 0 && (ud->legion || !ud->pidfile)) {
#else
		// stop only dumb daemons
		if (ud->pid > 0 && !ud->pidfile) {
#endif
			uwsgi_log("[uwsgi-daemons] stopping daemon (pid: %d): %s\n", (int) ud->pid, ud->command);
			// try to stop daemon gracefully, kill it if it won't die
			// if mercy is not set then wait up to 3 seconds
			time_t timeout = uwsgi_now() + (uwsgi.reload_mercy ? uwsgi.reload_mercy : 3);
			int waitpid_status;
			while (!kill(ud->pid, 0)) {
				kill(-(ud->pid), ud->stop_signal);
				sleep(1);
				waitpid(ud->pid, &waitpid_status, WNOHANG);
				if (uwsgi_now() >= timeout) {
					uwsgi_log("[uwsgi-daemons] daemon did not die in time, killing (pid: %d): %s\n", (int) ud->pid, ud->command);
					kill(-(ud->pid), SIGKILL);
					break;
				}
			}
			// unregister daemon to prevent it from being respawned
			ud->registered = 0;
		}
		ud = ud->next;
	}
}

static int daemon_spawn(void *);

void uwsgi_spawn_daemon(struct uwsgi_daemon *ud) {

	// skip unregistered daemons
	if (!ud->registered) return;

	ud->throttle = 0;

	if (uwsgi.current_time - ud->last_spawn <= 3) {
		ud->throttle = ud->respawns - (uwsgi.current_time - ud->last_spawn);
		// if ud->respawns == 0 then we can end up with throttle < 0
		if (ud->throttle <= 0) ud->throttle = 1;
	}

	pid_t pid = uwsgi_fork("uWSGI external daemon");
	if (pid < 0) {
		uwsgi_error("fork()");
		return;
	}

	if (pid > 0) {
		ud->has_daemonized = 0;
		ud->pid = pid;
		ud->status = 1;
		ud->pidfile_checks = 0;
		if (ud->respawns == 0) {
			ud->born = uwsgi_now();
		}

		ud->respawns++;
		ud->last_spawn = uwsgi_now();

	}
	else {
		// close uwsgi sockets
		uwsgi_close_all_sockets();
		uwsgi_close_all_fds();

#if defined(__linux__) && !defined(OBSOLETE_LINUX_KERNEL) && defined(CLONE_NEWPID)
		if (ud->ns_pid) {
			// we need to create a new session
			if (setsid() < 0) {
				uwsgi_error("setsid()");
				exit(1);
			}
			// avoid the need to set stop_signal in attach-daemon2
			signal(SIGTERM, end_me);

			char stack[PTHREAD_STACK_MIN];
                	pid_t pid = clone((int (*)(void *))daemon_spawn, stack + PTHREAD_STACK_MIN, SIGCHLD | CLONE_NEWPID, (void *) ud);
                        if (pid > 0) {

#ifdef PR_SET_PDEATHSIG
				if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0)) {
                                	uwsgi_error("uwsgi_spawn_daemon()/prctl()");
                        	}
#endif
                                // block all signals except SIGTERM
                                sigset_t smask;
                                sigfillset(&smask);
				sigdelset(&smask, SIGTERM);
                                sigprocmask(SIG_BLOCK, &smask, NULL);
                                int status;
                                if (waitpid(pid, &status, 0) < 0) {
                                        uwsgi_error("uwsgi_spawn_daemon()/waitpid()");
                                }
                                _exit(0);
                        }
			uwsgi_error("uwsgi_spawn_daemon()/clone()");
                        exit(1);
		}
#endif
		daemon_spawn((void *) ud);

	}
}


static int daemon_spawn(void *arg) {

	struct uwsgi_daemon *ud = (struct uwsgi_daemon *) arg;

		if (ud->gid) {
			if (setgid(ud->gid)) {
				uwsgi_error("uwsgi_spawn_daemon()/setgid()");
				exit(1);
			}
		}

		if (ud->uid) {
			if (setuid(ud->uid)) {
				uwsgi_error("uwsgi_spawn_daemon()/setuid()");
				exit(1);
			}
		}

		if (ud->daemonize) {
			/* refork... */
			pid_t pid = fork();
			if (pid < 0) {
				uwsgi_error("fork()");
				exit(1);
			}
			if (pid != 0) {
				_exit(0);
			}
			uwsgi_write_pidfile(ud->pidfile);
		}

		if (!uwsgi.daemons_honour_stdin && !ud->honour_stdin) {
			// /dev/null will became stdin
			uwsgi_remap_fd(0, "/dev/null");
		}

		if (setsid() < 0) {
			uwsgi_error("setsid()");
			exit(1);
		}

		if (!ud->pidfile) {
#ifdef PR_SET_PDEATHSIG
			if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0)) {
				uwsgi_error("prctl()");
			}
#endif
		}


		if (ud->throttle) {
			uwsgi_log("[uwsgi-daemons] throttling \"%s\" for %d seconds\n", ud->command, ud->throttle);
			sleep((unsigned int) ud->throttle);
		}

		uwsgi_log("[uwsgi-daemons] %sspawning \"%s\" (uid: %d gid: %d)\n", ud->respawns > 0 ? "re" : "", ud->command, (int) getuid(), (int) getgid());
		uwsgi_exec_command_with_args(ud->command);
		uwsgi_log("[uwsgi-daemons] unable to spawn \"%s\"\n", ud->command);

		// never here;
		exit(1);
}


void uwsgi_opt_add_daemon(char *opt, char *value, void *none) {

	struct uwsgi_daemon *uwsgi_ud = uwsgi.daemons, *old_ud;
	char *pidfile = NULL;
	int daemonize = 0;
	int freq = 10;
	char *space = NULL;
	int stop_signal = SIGTERM;
	int reload_signal = 0;

	char *command = uwsgi_str(value);

#ifdef UWSGI_SSL
	char *legion = NULL;
	if (!uwsgi_starts_with(opt, strlen(command), "legion-", 7)) {
		space = strchr(command, ' ');
		if (!space) {
			uwsgi_log("invalid legion daemon syntax: %s\n", command);
			exit(1);
		}
		*space = 0;
		legion = command;
		command = space+1;
	}
#endif

	if (!strcmp(opt, "smart-attach-daemon") || !strcmp(opt, "smart-attach-daemon2") || !strcmp(opt, "legion-smart-attach-daemon") || !strcmp(opt, "legion-smart-attach-daemon2")) {
		space = strchr(command, ' ');
		if (!space) {
			uwsgi_log("invalid smart-attach-daemon syntax: %s\n", command);
			exit(1);
		}
		*space = 0;
		pidfile = command;
		// check for freq
		char *comma = strchr(pidfile, ',');
		if (comma) {
			*comma = 0;
			freq = atoi(comma + 1);
		}
		command = space + 1;
		if (!strcmp(opt, "smart-attach-daemon2") || !strcmp(opt, "legion-smart-attach-daemon2")) {
			daemonize = 1;
		}
	}

	if (!uwsgi_ud) {
		uwsgi.daemons = uwsgi_calloc(sizeof(struct uwsgi_daemon));
		uwsgi_ud = uwsgi.daemons;
	}
	else {
		while (uwsgi_ud) {
			old_ud = uwsgi_ud;
			uwsgi_ud = uwsgi_ud->next;
		}

		uwsgi_ud = uwsgi_calloc(sizeof(struct uwsgi_daemon));
		old_ud->next = uwsgi_ud;
	}

	uwsgi_ud->command = command;
	uwsgi_ud->pid = 0;
	uwsgi_ud->status = 0;
	uwsgi_ud->freq = freq;
	uwsgi_ud->registered = 0;
	uwsgi_ud->next = NULL;
	uwsgi_ud->respawns = 0;
	uwsgi_ud->last_spawn = 0;
	uwsgi_ud->daemonize = daemonize;
	uwsgi_ud->pidfile = pidfile;
	uwsgi_ud->control = 0;
	uwsgi_ud->stop_signal = stop_signal;
	uwsgi_ud->reload_signal = reload_signal;
	if (!strcmp(opt, "attach-control-daemon")) {
		uwsgi_ud->control = 1;
	}
#ifdef UWSGI_SSL
	uwsgi_ud->legion = legion;
#endif

	uwsgi.daemons_cnt++;

}

void uwsgi_opt_add_daemon2(char *opt, char *value, void *none) {

        struct uwsgi_daemon *uwsgi_ud = uwsgi.daemons, *old_ud;

	char *d_command = NULL;
	char *d_freq = NULL;
	char *d_pidfile = NULL;
	char *d_control = NULL;
	char *d_legion = NULL;
	char *d_daemonize = NULL;
	char *d_touch = NULL;
	char *d_stopsignal = NULL;
	char *d_reloadsignal = NULL;
	char *d_stdin = NULL;
	char *d_uid = NULL;
	char *d_gid = NULL;
	char *d_ns_pid = NULL;

	char *arg = uwsgi_str(value);

	if (uwsgi_kvlist_parse(arg, strlen(arg), ',', '=',
		"command", &d_command,	
		"cmd", &d_command,	
		"exec", &d_command,	
		"freq", &d_freq,	
		"pidfile", &d_pidfile,	
		"control", &d_control,	
		"daemonize", &d_daemonize,	
		"daemon", &d_daemonize,	
		"touch", &d_touch,	
		"stopsignal", &d_stopsignal,	
		"stop_signal", &d_stopsignal,	
		"reloadsignal", &d_reloadsignal,	
		"reload_signal", &d_reloadsignal,	
		"stdin", &d_stdin,	
		"uid", &d_uid,	
		"gid", &d_gid,	
		"ns_pid", &d_ns_pid,	
	NULL)) {
		uwsgi_log("invalid --%s keyval syntax\n", opt);
		exit(1);
	}

	if (!d_command) {
		uwsgi_log("--%s: you need to specify a 'command' key\n", opt);
		exit(1);
	}

#ifndef UWSGI_SSL
	if (d_legion) {
		uwsgi_log("legion subsystem is not supported on this uWSGI version, rebuild with ssl support\n");
		exit(1);
	}
#endif



        if (!uwsgi_ud) {
                uwsgi.daemons = uwsgi_calloc(sizeof(struct uwsgi_daemon));
                uwsgi_ud = uwsgi.daemons;
        }
        else {
                while (uwsgi_ud) {
                        old_ud = uwsgi_ud;
                        uwsgi_ud = uwsgi_ud->next;
                }

                uwsgi_ud = uwsgi_calloc(sizeof(struct uwsgi_daemon));
                old_ud->next = uwsgi_ud;
        }
        uwsgi_ud->command = d_command;
        uwsgi_ud->freq = d_freq ? atoi(d_freq) : 10;
        uwsgi_ud->daemonize = d_daemonize ? 1 : 0;
        uwsgi_ud->pidfile = d_pidfile;
        uwsgi_ud->stop_signal = d_stopsignal ? atoi(d_stopsignal) : SIGTERM;
        uwsgi_ud->reload_signal = d_reloadsignal ? atoi(d_reloadsignal) : 0;
        uwsgi_ud->control = d_control ? 1 : 0;
	uwsgi_ud->uid = d_uid ? atoi(d_uid) : 0;
	uwsgi_ud->gid = d_gid ? atoi(d_gid) : 0;
	uwsgi_ud->honour_stdin = d_stdin ? 1 : 0;
#ifdef UWSGI_SSL
        uwsgi_ud->legion = d_legion;
#endif
        uwsgi_ud->ns_pid = d_ns_pid ? 1 : 0;

	if (d_touch) {
		size_t i,rlen = 0;
		char **argv = uwsgi_split_quoted(d_touch, strlen(d_touch), ";", &rlen);
		for(i=0;i<rlen;i++) {	
			uwsgi_string_new_list(&uwsgi_ud->touch, argv[i]);
		}
		if (argv) free(argv);
	}

        uwsgi.daemons_cnt++;

	free(arg);

}
コード例 #23
0
int adb_main(int is_daemon, int server_port)
{
#if !ADB_HOST
    int port;
    char value[PROPERTY_VALUE_MAX];

    umask(000);
#endif

    atexit(adb_cleanup);
#ifdef HAVE_WIN32_PROC
    SetConsoleCtrlHandler( ctrlc_handler, TRUE );
#elif defined(HAVE_FORKEXEC)
    // No SIGCHLD. Let the service subproc handle its children.
    signal(SIGPIPE, SIG_IGN);
#endif

    init_transport_registration();

#if ADB_HOST
    HOST = 1;
    usb_vendors_init();
    usb_init();
    local_init(DEFAULT_ADB_LOCAL_TRANSPORT_PORT);
    adb_auth_init();

    char local_name[30];
    build_local_name(local_name, sizeof(local_name), server_port);
    if(install_listener(local_name, "*smartsocket*", NULL)) {
        exit(1);
    }
#else
    property_get("ro.adb.secure", value, "0");
    auth_enabled = !strcmp(value, "1");
    if (auth_enabled)
        adb_auth_init();

    // Our external storage path may be different than apps, since
    // we aren't able to bind mount after dropping root.
    const char* adb_external_storage = getenv("ADB_EXTERNAL_STORAGE");
    if (NULL != adb_external_storage) {
        setenv("EXTERNAL_STORAGE", adb_external_storage, 1);
    } else {
        D("Warning: ADB_EXTERNAL_STORAGE is not set.  Leaving EXTERNAL_STORAGE"
          " unchanged.\n");
    }

    /* don't listen on a port (default 5037) if running in secure mode */
    /* don't run as root if we are running in secure mode */
    if (should_drop_privileges()) {
        struct __user_cap_header_struct header;
        struct __user_cap_data_struct cap;

        if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) != 0) {
            exit(1);
        }

        /* add extra groups:
        ** AID_ADB to access the USB driver
        ** AID_LOG to read system logs (adb logcat)
        ** AID_INPUT to diagnose input issues (getevent)
        ** AID_INET to diagnose network issues (netcfg, ping)
        ** AID_GRAPHICS to access the frame buffer
        ** AID_NET_BT and AID_NET_BT_ADMIN to diagnose bluetooth (hcidump)
        ** AID_SDCARD_R to allow reading from the SD card
        ** AID_SDCARD_RW to allow writing to the SD card
        ** AID_MOUNT to allow unmounting the SD card before rebooting
        ** AID_NET_BW_STATS to read out qtaguid statistics
        */
        gid_t groups[] = { AID_ADB, AID_LOG, AID_INPUT, AID_INET, AID_GRAPHICS,
                           AID_NET_BT, AID_NET_BT_ADMIN, AID_SDCARD_R, AID_SDCARD_RW,
                           AID_MOUNT, AID_NET_BW_STATS };
        if (setgroups(sizeof(groups)/sizeof(groups[0]), groups) != 0) {
            exit(1);
        }

        /* then switch user and group to "shell" */
        if (setgid(AID_SHELL) != 0) {
            exit(1);
        }
        if (setuid(AID_SHELL) != 0) {
            exit(1);
        }

        /* set CAP_SYS_BOOT capability, so "adb reboot" will succeed */
        header.version = _LINUX_CAPABILITY_VERSION;
        header.pid = 0;
        cap.effective = cap.permitted = (1 << CAP_SYS_BOOT);
        cap.inheritable = 0;
        capset(&header, &cap);

        D("Local port disabled\n");
    } else {
        char local_name[30];
        build_local_name(local_name, sizeof(local_name), server_port);
        if(install_listener(local_name, "*smartsocket*", NULL)) {
            exit(1);
        }
    }

    int usb = 0;
    if (access(USB_ADB_PATH, F_OK) == 0 || access(USB_FFS_ADB_EP0, F_OK) == 0) {
        // listen on USB
        usb_init();
        usb = 1;
    }

    // If one of these properties is set, also listen on that port
    // If one of the properties isn't set and we couldn't listen on usb,
    // listen on the default port.
     property_get("service.adb.tcp.port", value, "");
    if (!value[0]){
        property_get("persist.adb.tcp.port", value, "");
    }
    if (sscanf(value, "%d", &port) == 1 && port > 0) {
        printf("using port=%d\n", port);
        // listen on TCP port specified by service.adb.tcp.port property
        local_init(port);
    } else if (!usb) {
        // listen on default port
        local_init(DEFAULT_ADB_LOCAL_TRANSPORT_PORT);
    }

    D("adb_main(): pre init_jdwp()\n");
    XLOGD("adb_main(): pre init_jdwp()\n");
    init_jdwp();
    D("adb_main(): post init_jdwp()\n");
    XLOGD("adb_main(): post init_jdwp()\n");
#endif

    if (is_daemon)
    {
        // inform our parent that we are up and running.
#ifdef HAVE_WIN32_PROC
        DWORD  count;
        WriteFile( GetStdHandle( STD_OUTPUT_HANDLE ), "OK\n", 3, &count, NULL );
#elif defined(HAVE_FORKEXEC)
        fprintf(stderr, "OK\n");
#endif
        start_logging();
    }
    D("Event loop starting\n");
    XLOGD("Event loop starting\n");

    fdevent_loop();

    usb_cleanup();

    return 0;
}
コード例 #24
0
ファイル: setpriv.c プロジェクト: ArakniD/util-linux
static void dump(int dumplevel)
{
	int x;
	uid_t ru, eu, su;
	gid_t rg, eg, sg;

	if (getresuid(&ru, &eu, &su) == 0) {
		printf(_("uid: %u\n"), ru);
		printf(_("euid: %u\n"), eu);
		/* Saved and fs uids always equal euid. */
		if (3 <= dumplevel)
			printf(_("suid: %u\n"), su);
	} else
		warn(_("getresuid failed"));

	if (getresgid(&rg, &eg, &sg) == 0) {
		printf("gid: %ld\n", (long)rg);
		printf("egid: %ld\n", (long)eg);
		/* Saved and fs gids always equal egid. */
		if (dumplevel >= 3)
			printf("sgid: %ld\n", (long)sg);
	} else
		warn(_("getresgid failed"));

	dump_groups();

	x = prctl(PR_GET_NO_NEW_PRIVS, 0, 0, 0, 0);
	if (0 <= x)
		printf("no_new_privs: %d\n", x);
	else
		warn("setting no_new_privs failed");

	if (2 <= dumplevel) {
		printf(_("Effective capabilities: "));
		if (print_caps(stdout, CAPNG_EFFECTIVE) == 0)
			printf(_("[none]"));
		printf("\n");

		printf(_("Permitted capabilities: "));
		if (print_caps(stdout, CAPNG_PERMITTED) == 0)
			printf(_("[none]"));
		printf("\n");
	}

	printf(_("Inheritable capabilities: "));
	if (print_caps(stdout, CAPNG_INHERITABLE) == 0)
		printf(_("[none]"));
	printf("\n");

	printf(_("Capability bounding set: "));
	if (print_caps(stdout, CAPNG_BOUNDING_SET) == 0)
		printf(_("[none]"));
	printf("\n");

	dump_securebits();

	if (access(_PATH_SYS_SELINUX, F_OK) == 0)
		dump_label(_("SELinux label"));

	if (access(_PATH_SYS_APPARMOR, F_OK) == 0) {
		dump_label(_("AppArmor profile"));
	}
}
コード例 #25
0
void TimedEventQueue::threadEntry() {
    prctl(PR_SET_NAME, (unsigned long)"TimedEventQueue", 0, 0, 0);

    for (;;) {
        int64_t now_us = 0;
        sp<Event> event;

        {
            Mutex::Autolock autoLock(mLock);

            if (mStopped) {
                break;
            }

            while (mQueue.empty()) {
                mQueueNotEmptyCondition.wait(mLock);
            }

            event_id eventID = 0;
            for (;;) {
                if (mQueue.empty()) {
                    // The only event in the queue could have been cancelled
                    // while we were waiting for its scheduled time.
                    break;
                }

                List<QueueItem>::iterator it = mQueue.begin();
                eventID = (*it).event->eventID();

                now_us = getRealTimeUs();
                int64_t when_us = (*it).realtime_us;

                int64_t delay_us;
                if (when_us < 0 || when_us == INT64_MAX) {
                    delay_us = 0;
                } else {
                    delay_us = when_us - now_us;
                }

                if (delay_us <= 0) {
                    break;
                }

                static int64_t kMaxTimeoutUs = 10000000ll;  // 10 secs
                bool timeoutCapped = false;
                if (delay_us > kMaxTimeoutUs) {
                    LOGW("delay_us exceeds max timeout: %lld us", delay_us);

                    // We'll never block for more than 10 secs, instead
                    // we will split up the full timeout into chunks of
                    // 10 secs at a time. This will also avoid overflow
                    // when converting from us to ns.
                    delay_us = kMaxTimeoutUs;
                    timeoutCapped = true;
                }

                status_t err = mQueueHeadChangedCondition.waitRelative(
                        mLock, delay_us * 1000ll);

                if (!timeoutCapped && err == -ETIMEDOUT) {
                    // We finally hit the time this event is supposed to
                    // trigger.
                    now_us = getRealTimeUs();
                    break;
                }
            }

            // The event w/ this id may have been cancelled while we're
            // waiting for its trigger-time, in that case
            // removeEventFromQueue_l will return NULL.
            // Otherwise, the QueueItem will be removed
            // from the queue and the referenced event returned.
            event = removeEventFromQueue_l(eventID);
        }

        if (event != NULL) {
            // Fire event with the lock NOT held.
            event->fire(this, now_us);
        }
    }
}
コード例 #26
0
ファイル: setpriv.c プロジェクト: ArakniD/util-linux
int main(int argc, char **argv)
{
	enum {
		NNP = CHAR_MAX + 1,
		RUID,
		EUID,
		RGID,
		EGID,
		REUID,
		REGID,
		CLEAR_GROUPS,
		KEEP_GROUPS,
		GROUPS,
		INHCAPS,
		LISTCAPS,
		CAPBSET,
		SECUREBITS,
		SELINUX_LABEL,
		APPARMOR_PROFILE
	};

	static const struct option longopts[] = {
		{"dump", no_argument, 0, 'd'},
		{"nnp", no_argument, 0, NNP},
		{"no-new-privs", no_argument, 0, NNP},
		{"inh-caps", required_argument, 0, INHCAPS},
		{"list-caps", no_argument, 0, LISTCAPS},
		{"ruid", required_argument, 0, RUID},
		{"euid", required_argument, 0, EUID},
		{"rgid", required_argument, 0, RGID},
		{"egid", required_argument, 0, EGID},
		{"reuid", required_argument, 0, REUID},
		{"regid", required_argument, 0, REGID},
		{"clear-groups", no_argument, 0, CLEAR_GROUPS},
		{"keep-groups", no_argument, 0, KEEP_GROUPS},
		{"groups", required_argument, 0, GROUPS},
		{"bounding-set", required_argument, 0, CAPBSET},
		{"securebits", required_argument, 0, SECUREBITS},
		{"selinux-label", required_argument, 0, SELINUX_LABEL},
		{"apparmor-profile", required_argument, 0, APPARMOR_PROFILE},
		{"help", no_argument, 0, 'h'},
		{"version", no_argument, 0, 'V'},
		{NULL, 0, 0, 0}
	};

	static const ul_excl_t excl[] = {
		/* keep in same order with enum definitions */
		{CLEAR_GROUPS, KEEP_GROUPS, GROUPS},
		{0}
	};
	int excl_st[ARRAY_SIZE(excl)] = UL_EXCL_STATUS_INIT;

	int c;
	struct privctx opts;
	int dumplevel = 0;
	int total_opts = 0;
	int list_caps = 0;

	setlocale(LC_ALL, "");
	bindtextdomain(PACKAGE, LOCALEDIR);
	textdomain(PACKAGE);
	atexit(close_stdout);

	memset(&opts, 0, sizeof(opts));

	while ((c = getopt_long(argc, argv, "+dhV", longopts, NULL)) != -1) {
		err_exclusive_options(c, longopts, excl, excl_st);
		total_opts++;
		switch (c) {
		case 'd':
			dumplevel++;
			break;
		case NNP:
			if (opts.nnp)
				errx(EXIT_FAILURE,
				     _("duplicate --no-new-privs option"));
			opts.nnp = 1;
			break;
		case RUID:
			if (opts.have_ruid)
				errx(EXIT_FAILURE, _("duplicate ruid"));
			opts.have_ruid = 1;
			opts.ruid = get_user(optarg, _("failed to parse ruid"));
			break;
		case EUID:
			if (opts.have_euid)
				errx(EXIT_FAILURE, _("duplicate euid"));
			opts.have_euid = 1;
			opts.euid = get_user(optarg, _("failed to parse euid"));
			break;
		case REUID:
			if (opts.have_ruid || opts.have_euid)
				errx(EXIT_FAILURE, _("duplicate ruid or euid"));
			opts.have_ruid = opts.have_euid = 1;
			opts.ruid = opts.euid = get_user(optarg, _("failed to parse reuid"));
			break;
		case RGID:
			if (opts.have_rgid)
				errx(EXIT_FAILURE, _("duplicate rgid"));
			opts.have_rgid = 1;
			opts.rgid = get_group(optarg, _("failed to parse rgid"));
			break;
		case EGID:
			if (opts.have_egid)
				errx(EXIT_FAILURE, _("duplicate egid"));
			opts.have_egid = 1;
			opts.egid = get_group(optarg, _("failed to parse egid"));
			break;
		case REGID:
			if (opts.have_rgid || opts.have_egid)
				errx(EXIT_FAILURE, _("duplicate rgid or egid"));
			opts.have_rgid = opts.have_egid = 1;
			opts.rgid = opts.egid = get_group(optarg, _("failed to parse regid"));
			break;
		case CLEAR_GROUPS:
			if (opts.clear_groups)
				errx(EXIT_FAILURE,
				     _("duplicate --clear-groups option"));
			opts.clear_groups = 1;
			break;
		case KEEP_GROUPS:
			if (opts.keep_groups)
				errx(EXIT_FAILURE,
				     _("duplicate --keep-groups option"));
			opts.keep_groups = 1;
			break;
		case GROUPS:
			if (opts.have_groups)
				errx(EXIT_FAILURE,
				     _("duplicate --groups option"));
			parse_groups(&opts, optarg);
			break;
		case LISTCAPS:
			list_caps = 1;
			break;
		case INHCAPS:
			if (opts.caps_to_inherit)
				errx(EXIT_FAILURE,
				     _("duplicate --inh-caps option"));
			opts.caps_to_inherit = optarg;
			break;
		case CAPBSET:
			if (opts.bounding_set)
				errx(EXIT_FAILURE,
				     _("duplicate --bounding-set option"));
			opts.bounding_set = optarg;
			break;
		case SECUREBITS:
			if (opts.have_securebits)
				errx(EXIT_FAILURE,
				     _("duplicate --securebits option"));
			parse_securebits(&opts, optarg);
			break;
		case SELINUX_LABEL:
			if (opts.selinux_label)
				errx(EXIT_FAILURE,
				     _("duplicate --selinux-label option"));
			opts.selinux_label = optarg;
			break;
		case APPARMOR_PROFILE:
			if (opts.apparmor_profile)
				errx(EXIT_FAILURE,
				     _("duplicate --apparmor-profile option"));
			opts.apparmor_profile = optarg;
			break;
		case 'h':
			usage(stdout);
		case 'V':
			printf(UTIL_LINUX_VERSION);
			return EXIT_SUCCESS;
		case '?':
			usage(stderr);
		default:
			errx(EXIT_FAILURE, _("unrecognized option '%c'"), c);
		}
	}

	if (dumplevel) {
		if (total_opts != dumplevel || optind < argc)
			errx(EXIT_FAILURE,
			     _("--dump is incompatible with all other options"));
		dump(dumplevel);
		return EXIT_SUCCESS;
	}

	if (list_caps) {
		if (total_opts != 1 || optind < argc)
			errx(EXIT_FAILURE,
			     _("--list-caps must be specified alone"));
		list_known_caps();
		return EXIT_SUCCESS;
	}

	if (argc <= optind)
		errx(EXIT_FAILURE, _("No program specified"));

	if ((opts.have_rgid || opts.have_egid)
	    && !opts.keep_groups && !opts.clear_groups && !opts.have_groups)
		errx(EXIT_FAILURE,
		     _("--[re]gid requires --keep-groups, --clear-groups, or --groups"));

	if (opts.nnp)
		if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) == -1)
			err(EXIT_FAILURE, _("disallow granting new privileges failed"));

	if (opts.selinux_label)
		do_selinux_label(opts.selinux_label);
	if (opts.apparmor_profile)
		do_apparmor_profile(opts.apparmor_profile);

	if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1)
		err(EXIT_FAILURE, _("keep process capabilities failed"));

	/* We're going to want CAP_SETPCAP, CAP_SETUID, and CAP_SETGID if
	 * possible.  */
	bump_cap(CAP_SETPCAP);
	bump_cap(CAP_SETUID);
	bump_cap(CAP_SETGID);
	if (capng_apply(CAPNG_SELECT_CAPS) != 0)
		err(SETPRIV_EXIT_PRIVERR, _("activate capabilities"));

	if (opts.have_ruid || opts.have_euid) {
		do_setresuid(&opts);
		/* KEEPCAPS doesn't work for the effective mask. */
		if (capng_apply(CAPNG_SELECT_CAPS) != 0)
			err(SETPRIV_EXIT_PRIVERR, _("reactivate capabilities"));
	}

	if (opts.have_rgid || opts.have_egid)
		do_setresgid(&opts);

	if (opts.have_groups) {
		if (setgroups(opts.num_groups, opts.groups) != 0)
			err(SETPRIV_EXIT_PRIVERR, _("setgroups failed"));
	} else if (opts.clear_groups) {
		gid_t x = 0;
		if (setgroups(0, &x) != 0)
			err(SETPRIV_EXIT_PRIVERR, _("setgroups failed"));
	}

	if (opts.have_securebits)
		if (prctl(PR_SET_SECUREBITS, opts.securebits, 0, 0, 0) != 0)
			err(SETPRIV_EXIT_PRIVERR, _("set process securebits failed"));

	if (opts.bounding_set) {
		do_caps(CAPNG_BOUNDING_SET, opts.bounding_set);
		errno = EPERM;	/* capng doesn't set errno if we're missing CAP_SETPCAP */
		if (capng_apply(CAPNG_SELECT_BOUNDS) != 0)
			err(SETPRIV_EXIT_PRIVERR, _("apply bounding set"));
	}

	if (opts.caps_to_inherit) {
		do_caps(CAPNG_INHERITABLE, opts.caps_to_inherit);
		if (capng_apply(CAPNG_SELECT_CAPS) != 0)
			err(SETPRIV_EXIT_PRIVERR, _("apply capabilities"));
	}

	execvp(argv[optind], argv + optind);

	err(EXIT_FAILURE, _("cannot execute: %s"), argv[optind]);
}
コード例 #27
0
ファイル: server.c プロジェクト: carriercomm/lighttpd_ported
int main (int argc, char **argv) {
	server *srv = NULL;
	int print_config = 0;
	int test_config = 0;
	int i_am_root;
	int o;
	int num_childs = 0;
	int pid_fd = -1, fd;
	size_t i;
#ifdef HAVE_SIGACTION
	struct sigaction act;
#endif
#ifdef HAVE_GETRLIMIT
	struct rlimit rlim;
#endif

#ifdef USE_ALARM
	struct itimerval interval;

	interval.it_interval.tv_sec = 1;
	interval.it_interval.tv_usec = 0;
	interval.it_value.tv_sec = 1;
	interval.it_value.tv_usec = 0;
#endif


	/* for nice %b handling in strfime() */
	setlocale(LC_TIME, "C");

	if (NULL == (srv = server_init())) {
		fprintf(stderr, "did this really happen?\n");
		return -1;
	}

	/* init structs done */

	srv->srvconf.port = 0;
#ifdef HAVE_GETUID
	i_am_root = (getuid() == 0);
#else
	i_am_root = 0;
#endif
	srv->srvconf.dont_daemonize = 0;

	while(-1 != (o = getopt(argc, argv, "f:m:hvVDpt"))) {
		switch(o) {
		case 'f':
			if (srv->config_storage) {
				log_error_write(srv, __FILE__, __LINE__, "s",
						"Can only read one config file. Use the include command to use multiple config files.");

				server_free(srv);
				return -1;
			}
			if (config_read(srv, optarg)) {
				server_free(srv);
				return -1;
			}
			break;
		case 'm':
			buffer_copy_string(srv->srvconf.modules_dir, optarg);
			break;
		case 'p': print_config = 1; break;
		case 't': test_config = 1; break;
		case 'D': srv->srvconf.dont_daemonize = 1; break;
		case 'v': show_version(); return 0;
		case 'V': show_features(); return 0;
		case 'h': show_help(); return 0;
		default:
			show_help();
			server_free(srv);
			return -1;
		}
	}

	if (!srv->config_storage) {
		log_error_write(srv, __FILE__, __LINE__, "s",
				"No configuration available. Try using -f option.");

		server_free(srv);
		return -1;
	}

	if (print_config) {
		data_unset *dc = srv->config_context->data[0];
		if (dc) {
			dc->print(dc, 0);
			fprintf(stdout, "\n");
		} else {
			/* shouldn't happend */
			fprintf(stderr, "global config not found\n");
		}
	}

	if (test_config) {
		printf("Syntax OK\n");
	}

	if (test_config || print_config) {
		server_free(srv);
		return 0;
	}

	/* close stdin and stdout, as they are not needed */
	openDevNull(STDIN_FILENO);
	openDevNull(STDOUT_FILENO);

	if (0 != config_set_defaults(srv)) {
		log_error_write(srv, __FILE__, __LINE__, "s",
				"setting default values failed");
		server_free(srv);
		return -1;
	}

	/* UID handling */
#ifdef HAVE_GETUID
	if (!i_am_root && issetugid()) {
		/* we are setuid-root */

		log_error_write(srv, __FILE__, __LINE__, "s",
				"Are you nuts ? Don't apply a SUID bit to this binary");

		server_free(srv);
		return -1;
	}
#endif

	/* check document-root */
	if (buffer_string_is_empty(srv->config_storage[0]->document_root)) {
		log_error_write(srv, __FILE__, __LINE__, "s",
				"document-root is not set\n");

		server_free(srv);

		return -1;
	}

	if (plugins_load(srv)) {
		log_error_write(srv, __FILE__, __LINE__, "s",
				"loading plugins finally failed");

		plugins_free(srv);
		server_free(srv);

		return -1;
	}

	/* open pid file BEFORE chroot */
	if (!buffer_string_is_empty(srv->srvconf.pid_file)) {
		if (-1 == (pid_fd = open(srv->srvconf.pid_file->ptr, O_WRONLY | O_CREAT | O_EXCL | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) {
			struct stat st;
			if (errno != EEXIST) {
				log_error_write(srv, __FILE__, __LINE__, "sbs",
					"opening pid-file failed:", srv->srvconf.pid_file, strerror(errno));
				return -1;
			}

			if (0 != stat(srv->srvconf.pid_file->ptr, &st)) {
				log_error_write(srv, __FILE__, __LINE__, "sbs",
						"stating existing pid-file failed:", srv->srvconf.pid_file, strerror(errno));
			}

			if (!S_ISREG(st.st_mode)) {
				log_error_write(srv, __FILE__, __LINE__, "sb",
						"pid-file exists and isn't regular file:", srv->srvconf.pid_file);
				return -1;
			}

			if (-1 == (pid_fd = open(srv->srvconf.pid_file->ptr, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) {
				log_error_write(srv, __FILE__, __LINE__, "sbs",
						"opening pid-file failed:", srv->srvconf.pid_file, strerror(errno));
				return -1;
			}
		}
	}

	if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
		/* select limits itself
		 *
		 * as it is a hard limit and will lead to a segfault we add some safety
		 * */
		srv->max_fds = FD_SETSIZE - 200;
	} else {
		srv->max_fds = 4096;
	}

	if (i_am_root) {
		struct group *grp = NULL;
		struct passwd *pwd = NULL;
		int use_rlimit = 1;

#ifdef HAVE_VALGRIND_VALGRIND_H
		if (RUNNING_ON_VALGRIND) use_rlimit = 0;
#endif

#ifdef HAVE_GETRLIMIT
		if (0 != getrlimit(RLIMIT_NOFILE, &rlim)) {
			log_error_write(srv, __FILE__, __LINE__,
					"ss", "couldn't get 'max filedescriptors'",
					strerror(errno));
			return -1;
		}

		if (use_rlimit && srv->srvconf.max_fds) {
			/* set rlimits */

			rlim.rlim_cur = srv->srvconf.max_fds;
			rlim.rlim_max = srv->srvconf.max_fds;

			if (0 != setrlimit(RLIMIT_NOFILE, &rlim)) {
				log_error_write(srv, __FILE__, __LINE__,
						"ss", "couldn't set 'max filedescriptors'",
						strerror(errno));
				return -1;
			}
		}

		if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
			srv->max_fds = rlim.rlim_cur < ((int)FD_SETSIZE) - 200 ? rlim.rlim_cur : FD_SETSIZE - 200;
		} else {
			srv->max_fds = rlim.rlim_cur;
		}

		/* set core file rlimit, if enable_cores is set */
		if (use_rlimit && srv->srvconf.enable_cores && getrlimit(RLIMIT_CORE, &rlim) == 0) {
			rlim.rlim_cur = rlim.rlim_max;
			setrlimit(RLIMIT_CORE, &rlim);
		}
#endif
		if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
			/* don't raise the limit above FD_SET_SIZE */
			if (srv->max_fds > ((int)FD_SETSIZE) - 200) {
				log_error_write(srv, __FILE__, __LINE__, "sd",
						"can't raise max filedescriptors above",  FD_SETSIZE - 200,
						"if event-handler is 'select'. Use 'poll' or something else or reduce server.max-fds.");
				return -1;
			}
		}


#ifdef HAVE_PWD_H
		/* set user and group */
		if (!buffer_string_is_empty(srv->srvconf.username)) {
			if (NULL == (pwd = getpwnam(srv->srvconf.username->ptr))) {
				log_error_write(srv, __FILE__, __LINE__, "sb",
						"can't find username", srv->srvconf.username);
				return -1;
			}

			if (pwd->pw_uid == 0) {
				log_error_write(srv, __FILE__, __LINE__, "s",
						"I will not set uid to 0\n");
				return -1;
			}
		}

		if (!buffer_string_is_empty(srv->srvconf.groupname)) {
			if (NULL == (grp = getgrnam(srv->srvconf.groupname->ptr))) {
				log_error_write(srv, __FILE__, __LINE__, "sb",
					"can't find groupname", srv->srvconf.groupname);
				return -1;
			}
			if (grp->gr_gid == 0) {
				log_error_write(srv, __FILE__, __LINE__, "s",
						"I will not set gid to 0\n");
				return -1;
			}
		}
#endif
		/* we need root-perms for port < 1024 */
		if (0 != network_init(srv)) {
			plugins_free(srv);
			server_free(srv);

			return -1;
		}
#ifdef HAVE_PWD_H
		/* 
		 * Change group before chroot, when we have access
		 * to /etc/group
		 * */
		if (NULL != grp) {
			if (-1 == setgid(grp->gr_gid)) {
				log_error_write(srv, __FILE__, __LINE__, "ss", "setgid failed: ", strerror(errno));
				return -1;
			}
			if (-1 == setgroups(0, NULL)) {
				log_error_write(srv, __FILE__, __LINE__, "ss", "setgroups failed: ", strerror(errno));
				return -1;
			}
			if (!buffer_string_is_empty(srv->srvconf.username)) {
				initgroups(srv->srvconf.username->ptr, grp->gr_gid);
			}
		}
#endif
#ifdef HAVE_CHROOT
		if (!buffer_string_is_empty(srv->srvconf.changeroot)) {
			tzset();

			if (-1 == chroot(srv->srvconf.changeroot->ptr)) {
				log_error_write(srv, __FILE__, __LINE__, "ss", "chroot failed: ", strerror(errno));
				return -1;
			}
			if (-1 == chdir("/")) {
				log_error_write(srv, __FILE__, __LINE__, "ss", "chdir failed: ", strerror(errno));
				return -1;
			}
		}
#endif
#ifdef HAVE_PWD_H
		/* drop root privs */
		if (NULL != pwd) {
			if (-1 == setuid(pwd->pw_uid)) {
				log_error_write(srv, __FILE__, __LINE__, "ss", "setuid failed: ", strerror(errno));
				return -1;
			}
		}
#endif
#if defined(HAVE_SYS_PRCTL_H) && defined(PR_SET_DUMPABLE)
		/**
		 * on IRIX 6.5.30 they have prctl() but no DUMPABLE
		 */
		if (srv->srvconf.enable_cores) {
			prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
		}
#endif
	} else {

#ifdef HAVE_GETRLIMIT
		if (0 != getrlimit(RLIMIT_NOFILE, &rlim)) {
			log_error_write(srv, __FILE__, __LINE__,
					"ss", "couldn't get 'max filedescriptors'",
					strerror(errno));
			return -1;
		}

		/**
		 * we are not root can can't increase the fd-limit, but we can reduce it
		 */
		if (srv->srvconf.max_fds && srv->srvconf.max_fds < rlim.rlim_cur) {
			/* set rlimits */

			rlim.rlim_cur = srv->srvconf.max_fds;

			if (0 != setrlimit(RLIMIT_NOFILE, &rlim)) {
				log_error_write(srv, __FILE__, __LINE__,
						"ss", "couldn't set 'max filedescriptors'",
						strerror(errno));
				return -1;
			}
		}

		if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
			srv->max_fds = rlim.rlim_cur < ((int)FD_SETSIZE) - 200 ? rlim.rlim_cur : FD_SETSIZE - 200;
		} else {
			srv->max_fds = rlim.rlim_cur;
		}

		/* set core file rlimit, if enable_cores is set */
		if (srv->srvconf.enable_cores && getrlimit(RLIMIT_CORE, &rlim) == 0) {
			rlim.rlim_cur = rlim.rlim_max;
			setrlimit(RLIMIT_CORE, &rlim);
		}

#endif
		if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
			/* don't raise the limit above FD_SET_SIZE */
			if (srv->max_fds > ((int)FD_SETSIZE) - 200) {
				log_error_write(srv, __FILE__, __LINE__, "sd",
						"can't raise max filedescriptors above",  FD_SETSIZE - 200,
						"if event-handler is 'select'. Use 'poll' or something else or reduce server.max-fds.");
				return -1;
			}
		}

		if (0 != network_init(srv)) {
			plugins_free(srv);
			server_free(srv);

			return -1;
		}
	}

	/* set max-conns */
	if (srv->srvconf.max_conns > srv->max_fds/2) {
		/* we can't have more connections than max-fds/2 */
		log_error_write(srv, __FILE__, __LINE__, "sdd", "can't have more connections than fds/2: ", srv->srvconf.max_conns, srv->max_fds);
		srv->max_conns = srv->max_fds/2;
	} else if (srv->srvconf.max_conns) {
		/* otherwise respect the wishes of the user */
		srv->max_conns = srv->srvconf.max_conns;
	} else {
		/* or use the default: we really don't want to hit max-fds */
		srv->max_conns = srv->max_fds/3;
	}

	if (HANDLER_GO_ON != plugins_call_init(srv)) {
		log_error_write(srv, __FILE__, __LINE__, "s", "Initialization of plugins failed. Going down.");

		plugins_free(srv);
		network_close(srv);
		server_free(srv);

		return -1;
	}

#ifdef HAVE_FORK
	/* network is up, let's deamonize ourself */
	if (srv->srvconf.dont_daemonize == 0) daemonize();
#endif


#ifdef HAVE_SIGACTION
	memset(&act, 0, sizeof(act));
	act.sa_handler = SIG_IGN;
	sigaction(SIGPIPE, &act, NULL);
	sigaction(SIGUSR1, &act, NULL);
# if defined(SA_SIGINFO)
	act.sa_sigaction = sigaction_handler;
	sigemptyset(&act.sa_mask);
	act.sa_flags = SA_SIGINFO;
# else
	act.sa_handler = signal_handler;
	sigemptyset(&act.sa_mask);
	act.sa_flags = 0;
# endif
	sigaction(SIGINT,  &act, NULL);
	sigaction(SIGTERM, &act, NULL);
	sigaction(SIGHUP,  &act, NULL);
	sigaction(SIGALRM, &act, NULL);
	sigaction(SIGCHLD, &act, NULL);

#elif defined(HAVE_SIGNAL)
	/* ignore the SIGPIPE from sendfile() */
	signal(SIGPIPE, SIG_IGN);
	signal(SIGUSR1, SIG_IGN);
	signal(SIGALRM, signal_handler);
	signal(SIGTERM, signal_handler);
	signal(SIGHUP,  signal_handler);
	signal(SIGCHLD,  signal_handler);
	signal(SIGINT,  signal_handler);
#endif

#ifdef USE_ALARM
	signal(SIGALRM, signal_handler);

	/* setup periodic timer (1 second) */
	if (setitimer(ITIMER_REAL, &interval, NULL)) {
		log_error_write(srv, __FILE__, __LINE__, "s", "setting timer failed");
		return -1;
	}

	getitimer(ITIMER_REAL, &interval);
#endif


	srv->gid = getgid();
	srv->uid = getuid();

	/* write pid file */
	if (pid_fd != -1) {
		buffer_copy_int(srv->tmp_buf, getpid());
		buffer_append_string_len(srv->tmp_buf, CONST_STR_LEN("\n"));
		if (-1 == write_all(pid_fd, CONST_BUF_LEN(srv->tmp_buf))) {
			log_error_write(srv, __FILE__, __LINE__, "ss", "Couldn't write pid file:", strerror(errno));
			close(pid_fd);
			return -1;
		}
		close(pid_fd);
		pid_fd = -1;
	}

	/* Close stderr ASAP in the child process to make sure that nothing
	 * is being written to that fd which may not be valid anymore. */
	if (-1 == log_error_open(srv)) {
		log_error_write(srv, __FILE__, __LINE__, "s", "Opening errorlog failed. Going down.");

		plugins_free(srv);
		network_close(srv);
		server_free(srv);
		return -1;
	}

	if (HANDLER_GO_ON != plugins_call_set_defaults(srv)) {
		log_error_write(srv, __FILE__, __LINE__, "s", "Configuration of plugins failed. Going down.");

		plugins_free(srv);
		network_close(srv);
		server_free(srv);

		return -1;
	}

	/* dump unused config-keys */
	for (i = 0; i < srv->config_context->used; i++) {
		array *config = ((data_config *)srv->config_context->data[i])->value;
		size_t j;

		for (j = 0; config && j < config->used; j++) {
			data_unset *du = config->data[j];

			/* all var.* is known as user defined variable */
			if (strncmp(du->key->ptr, "var.", sizeof("var.") - 1) == 0) {
				continue;
			}

			if (NULL == array_get_element(srv->config_touched, du->key->ptr)) {
				log_error_write(srv, __FILE__, __LINE__, "sbs",
						"WARNING: unknown config-key:",
						du->key,
						"(ignored)");
			}
		}
	}

	if (srv->config_unsupported) {
		log_error_write(srv, __FILE__, __LINE__, "s",
				"Configuration contains unsupported keys. Going down.");
	}

	if (srv->config_deprecated) {
		log_error_write(srv, __FILE__, __LINE__, "s",
				"Configuration contains deprecated keys. Going down.");
	}

	if (srv->config_unsupported || srv->config_deprecated) {
		plugins_free(srv);
		network_close(srv);
		server_free(srv);

		return -1;
	}


#ifdef HAVE_FORK
	/* start watcher and workers */
	num_childs = srv->srvconf.max_worker;
	if (num_childs > 0) {
		int child = 0;
		while (!child && !srv_shutdown && !graceful_shutdown) {
			if (num_childs > 0) {
				switch (fork()) {
				case -1:
					return -1;
				case 0:
					child = 1;
					break;
				default:
					num_childs--;
					break;
				}
			} else {
				int status;

				if (-1 != wait(&status)) {
					/** 
					 * one of our workers went away 
					 */
					num_childs++;
				} else {
					switch (errno) {
					case EINTR:
						/**
						 * if we receive a SIGHUP we have to close our logs ourself as we don't 
						 * have the mainloop who can help us here
						 */
						if (handle_sig_hup) {
							handle_sig_hup = 0;

							log_error_cycle(srv);

							/**
							 * forward to all procs in the process-group
							 * 
							 * we also send it ourself
							 */
							if (!forwarded_sig_hup) {
								forwarded_sig_hup = 1;
								kill(0, SIGHUP);
							}
						}
						break;
					default:
						break;
					}
				}
			}
		}

		/**
		 * for the parent this is the exit-point 
		 */
		if (!child) {
			/** 
			 * kill all children too 
			 */
			if (graceful_shutdown) {
				kill(0, SIGINT);
			} else if (srv_shutdown) {
				kill(0, SIGTERM);
			}

			log_error_close(srv);
			network_close(srv);
			connections_free(srv);
			plugins_free(srv);
			server_free(srv);
			return 0;
		}
	}
#endif

	if (NULL == (srv->ev = fdevent_init(srv, srv->max_fds + 1, srv->event_handler))) {
		log_error_write(srv, __FILE__, __LINE__,
				"s", "fdevent_init failed");
		return -1;
	}

	/* libev backend overwrites our SIGCHLD handler and calls waitpid on SIGCHLD; we want our own SIGCHLD handling. */
#ifdef HAVE_SIGACTION
	sigaction(SIGCHLD, &act, NULL);
#elif defined(HAVE_SIGNAL)
	signal(SIGCHLD,  signal_handler);
#endif

	/*
	 * kqueue() is called here, select resets its internals,
	 * all server sockets get their handlers
	 *
	 * */
	if (0 != network_register_fdevents(srv)) {
		plugins_free(srv);
		network_close(srv);
		server_free(srv);

		return -1;
	}

	/* might fail if user is using fam (not gamin) and famd isn't running */
	if (NULL == (srv->stat_cache = stat_cache_init())) {
		log_error_write(srv, __FILE__, __LINE__, "s",
			"stat-cache could not be setup, dieing.");
		return -1;
	}

#ifdef HAVE_FAM_H
	/* setup FAM */
	if (srv->srvconf.stat_cache_engine == STAT_CACHE_ENGINE_FAM) {
		if (0 != FAMOpen2(&srv->stat_cache->fam, "lighttpd")) {
			log_error_write(srv, __FILE__, __LINE__, "s",
					 "could not open a fam connection, dieing.");
			return -1;
		}
#ifdef HAVE_FAMNOEXISTS
		FAMNoExists(&srv->stat_cache->fam);
#endif

		fdevent_register(srv->ev, FAMCONNECTION_GETFD(&srv->stat_cache->fam), stat_cache_handle_fdevent, NULL);
		fdevent_event_set(srv->ev, &(srv->stat_cache->fam_fcce_ndx), FAMCONNECTION_GETFD(&srv->stat_cache->fam), FDEVENT_IN);
	}
#endif


	/* get the current number of FDs */
	srv->cur_fds = open("/dev/null", O_RDONLY);
	close(srv->cur_fds);

	for (i = 0; i < srv->srv_sockets.used; i++) {
		server_socket *srv_socket = srv->srv_sockets.ptr[i];
		if (-1 == fdevent_fcntl_set(srv->ev, srv_socket->fd)) {
			log_error_write(srv, __FILE__, __LINE__, "ss", "fcntl failed:", strerror(errno));
			return -1;
		}
	}

	/* main-loop */
	while (!srv_shutdown) {
		int n;
		size_t ndx;
		time_t min_ts;

		if (handle_sig_hup) {
			handler_t r;

			/* reset notification */
			handle_sig_hup = 0;


			/* cycle logfiles */

			switch(r = plugins_call_handle_sighup(srv)) {
			case HANDLER_GO_ON:
				break;
			default:
				log_error_write(srv, __FILE__, __LINE__, "sd", "sighup-handler return with an error", r);
				break;
			}

			if (-1 == log_error_cycle(srv)) {
				log_error_write(srv, __FILE__, __LINE__, "s", "cycling errorlog failed, dying");

				return -1;
			} else {
#ifdef HAVE_SIGACTION
				log_error_write(srv, __FILE__, __LINE__, "sdsd", 
					"logfiles cycled UID =",
					last_sighup_info.si_uid,
					"PID =",
					last_sighup_info.si_pid);
#else
				log_error_write(srv, __FILE__, __LINE__, "s", 
					"logfiles cycled");
#endif
			}
		}

		if (handle_sig_alarm) {
			/* a new second */

#ifdef USE_ALARM
			/* reset notification */
			handle_sig_alarm = 0;
#endif

			/* get current time */
			min_ts = time(NULL);

			if (min_ts != srv->cur_ts) {
#ifdef DEBUG_CONNECTION_STATES
				int cs = 0;
#endif
				connections *conns = srv->conns;
				handler_t r;

				switch(r = plugins_call_handle_trigger(srv)) {
				case HANDLER_GO_ON:
					break;
				case HANDLER_ERROR:
					log_error_write(srv, __FILE__, __LINE__, "s", "one of the triggers failed");
					break;
				default:
					log_error_write(srv, __FILE__, __LINE__, "d", r);
					break;
				}

				/* trigger waitpid */
				srv->cur_ts = min_ts;

				/* cleanup stat-cache */
				stat_cache_trigger_cleanup(srv);
				/**
				 * check all connections for timeouts
				 *
				 */
				for (ndx = 0; ndx < conns->used; ndx++) {
					int changed = 0;
					connection *con;
					int t_diff;

					con = conns->ptr[ndx];

					if (con->state == CON_STATE_READ ||
					    con->state == CON_STATE_READ_POST) {
						if (con->request_count == 1 || con->state == CON_STATE_READ_POST) {
							if (srv->cur_ts - con->read_idle_ts > con->conf.max_read_idle) {
								/* time - out */
								if (con->conf.log_request_handling) {
									log_error_write(srv, __FILE__, __LINE__, "sd",
										"connection closed - read timeout:", con->fd);
								}

								connection_set_state(srv, con, CON_STATE_ERROR);
								changed = 1;
							}
						} else {
							if (srv->cur_ts - con->read_idle_ts > con->keep_alive_idle) {
								/* time - out */
								if (con->conf.log_request_handling) {
									log_error_write(srv, __FILE__, __LINE__, "sd",
										"connection closed - keep-alive timeout:", con->fd);
								}

								connection_set_state(srv, con, CON_STATE_ERROR);
								changed = 1;
							}
						}
					}

					if ((con->state == CON_STATE_WRITE) &&
					    (con->write_request_ts != 0)) {
#if 0
						if (srv->cur_ts - con->write_request_ts > 60) {
							log_error_write(srv, __FILE__, __LINE__, "sdd",
									"connection closed - pre-write-request-timeout:", con->fd, srv->cur_ts - con->write_request_ts);
						}
#endif

						if (srv->cur_ts - con->write_request_ts > con->conf.max_write_idle) {
							/* time - out */
							if (con->conf.log_timeouts) {
								log_error_write(srv, __FILE__, __LINE__, "sbsosds",
									"NOTE: a request for",
									con->request.uri,
									"timed out after writing",
									con->bytes_written,
									"bytes. We waited",
									(int)con->conf.max_write_idle,
									"seconds. If this a problem increase server.max-write-idle");
							}
							connection_set_state(srv, con, CON_STATE_ERROR);
							changed = 1;
						}
					}

					if (con->state == CON_STATE_CLOSE && (srv->cur_ts - con->close_timeout_ts > HTTP_LINGER_TIMEOUT)) {
						changed = 1;
					}

					/* we don't like div by zero */
					if (0 == (t_diff = srv->cur_ts - con->connection_start)) t_diff = 1;

					if (con->traffic_limit_reached &&
					    (con->conf.kbytes_per_second == 0 ||
					     ((con->bytes_written / t_diff) < con->conf.kbytes_per_second * 1024))) {
						/* enable connection again */
						con->traffic_limit_reached = 0;

						changed = 1;
					}

					if (changed) {
						connection_state_machine(srv, con);
					}
					con->bytes_written_cur_second = 0;
					*(con->conf.global_bytes_per_second_cnt_ptr) = 0;

#if DEBUG_CONNECTION_STATES
					if (cs == 0) {
						fprintf(stderr, "connection-state: ");
						cs = 1;
					}

					fprintf(stderr, "c[%d,%d]: %s ",
						con->fd,
						con->fcgi.fd,
						connection_get_state(con->state));
#endif
				}

#ifdef DEBUG_CONNECTION_STATES
				if (cs == 1) fprintf(stderr, "\n");
#endif
			}
		}

		if (srv->sockets_disabled) {
			/* our server sockets are disabled, why ? */

			if ((srv->cur_fds + srv->want_fds < srv->max_fds * 8 / 10) && /* we have enough unused fds */
			    (srv->conns->used <= srv->max_conns * 9 / 10) &&
			    (0 == graceful_shutdown)) {
				for (i = 0; i < srv->srv_sockets.used; i++) {
					server_socket *srv_socket = srv->srv_sockets.ptr[i];
					fdevent_event_set(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd, FDEVENT_IN);
				}

				log_error_write(srv, __FILE__, __LINE__, "s", "[note] sockets enabled again");

				srv->sockets_disabled = 0;
			}
		} else {
			if ((srv->cur_fds + srv->want_fds > srv->max_fds * 9 / 10) || /* out of fds */
			    (srv->conns->used >= srv->max_conns) || /* out of connections */
			    (graceful_shutdown)) { /* graceful_shutdown */

				/* disable server-fds */

				for (i = 0; i < srv->srv_sockets.used; i++) {
					server_socket *srv_socket = srv->srv_sockets.ptr[i];
					fdevent_event_del(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd);

					if (graceful_shutdown) {
						/* we don't want this socket anymore,
						 *
						 * closing it right away will make it possible for
						 * the next lighttpd to take over (graceful restart)
						 *  */

						fdevent_unregister(srv->ev, srv_socket->fd);
						close(srv_socket->fd);
						srv_socket->fd = -1;

						/* network_close() will cleanup after us */

						if (!buffer_string_is_empty(srv->srvconf.pid_file) &&
						    buffer_string_is_empty(srv->srvconf.changeroot)) {
							if (0 != unlink(srv->srvconf.pid_file->ptr)) {
								if (errno != EACCES && errno != EPERM) {
									log_error_write(srv, __FILE__, __LINE__, "sbds",
											"unlink failed for:",
											srv->srvconf.pid_file,
											errno,
											strerror(errno));
								}
							}
						}
					}
				}

				if (graceful_shutdown) {
					log_error_write(srv, __FILE__, __LINE__, "s", "[note] graceful shutdown started");
				} else if (srv->conns->used >= srv->max_conns) {
					log_error_write(srv, __FILE__, __LINE__, "s", "[note] sockets disabled, connection limit reached");
				} else {
					log_error_write(srv, __FILE__, __LINE__, "s", "[note] sockets disabled, out-of-fds");
				}

				srv->sockets_disabled = 1;
			}
		}

		if (graceful_shutdown && srv->conns->used == 0) {
			/* we are in graceful shutdown phase and all connections are closed
			 * we are ready to terminate without harming anyone */
			srv_shutdown = 1;
		}

		/* we still have some fds to share */
		if (srv->want_fds) {
			/* check the fdwaitqueue for waiting fds */
			int free_fds = srv->max_fds - srv->cur_fds - 16;
			connection *con;

			for (; free_fds > 0 && NULL != (con = fdwaitqueue_unshift(srv, srv->fdwaitqueue)); free_fds--) {
				connection_state_machine(srv, con);

				srv->want_fds--;
			}
		}

		if ((n = fdevent_poll(srv->ev, 1000)) > 0) {
			/* n is the number of events */
			int revents;
			int fd_ndx;
#if 0
			if (n > 0) {
				log_error_write(srv, __FILE__, __LINE__, "sd",
						"polls:", n);
			}
#endif
			fd_ndx = -1;
			do {
				fdevent_handler handler;
				void *context;
				handler_t r;

				fd_ndx  = fdevent_event_next_fdndx (srv->ev, fd_ndx);
				if (-1 == fd_ndx) break; /* not all fdevent handlers know how many fds got an event */

				revents = fdevent_event_get_revent (srv->ev, fd_ndx);
				fd      = fdevent_event_get_fd     (srv->ev, fd_ndx);
				handler = fdevent_get_handler(srv->ev, fd);
				context = fdevent_get_context(srv->ev, fd);

				/* connection_handle_fdevent needs a joblist_append */
#if 0
				log_error_write(srv, __FILE__, __LINE__, "sdd",
						"event for", fd, revents);
#endif
				switch (r = (*handler)(srv, context, revents)) {
				case HANDLER_FINISHED:
				case HANDLER_GO_ON:
				case HANDLER_WAIT_FOR_EVENT:
				case HANDLER_WAIT_FOR_FD:
					break;
				case HANDLER_ERROR:
					/* should never happen */
					SEGFAULT();
					break;
				default:
					log_error_write(srv, __FILE__, __LINE__, "d", r);
					break;
				}
			} while (--n > 0);
		} else if (n < 0 && errno != EINTR) {
			log_error_write(srv, __FILE__, __LINE__, "ss",
					"fdevent_poll failed:",
					strerror(errno));
		}

		for (ndx = 0; ndx < srv->joblist->used; ndx++) {
			connection *con = srv->joblist->ptr[ndx];
			handler_t r;

			connection_state_machine(srv, con);

			switch(r = plugins_call_handle_joblist(srv, con)) {
			case HANDLER_FINISHED:
			case HANDLER_GO_ON:
				break;
			default:
				log_error_write(srv, __FILE__, __LINE__, "d", r);
				break;
			}

			con->in_joblist = 0;
		}

		srv->joblist->used = 0;
	}

	if (!buffer_string_is_empty(srv->srvconf.pid_file) &&
	    buffer_string_is_empty(srv->srvconf.changeroot) &&
	    0 == graceful_shutdown) {
		if (0 != unlink(srv->srvconf.pid_file->ptr)) {
			if (errno != EACCES && errno != EPERM) {
				log_error_write(srv, __FILE__, __LINE__, "sbds",
						"unlink failed for:",
						srv->srvconf.pid_file,
						errno,
						strerror(errno));
			}
		}
	}

#ifdef HAVE_SIGACTION
	log_error_write(srv, __FILE__, __LINE__, "sdsd", 
			"server stopped by UID =",
			last_sigterm_info.si_uid,
			"PID =",
			last_sigterm_info.si_pid);
#else
	log_error_write(srv, __FILE__, __LINE__, "s", 
			"server stopped");
#endif

	/* clean-up */
	log_error_close(srv);
	network_close(srv);
	connections_free(srv);
	plugins_free(srv);
	server_free(srv);

	return 0;
}
コード例 #28
0
ファイル: fpm_unix.c プロジェクト: Leon2012/php_nginx
int fpm_unix_init_child(struct fpm_worker_pool_s *wp) /* {{{ */
{
	int is_root = !geteuid();
	int made_chroot = 0;

	if (wp->config->rlimit_files) {
		struct rlimit r;

		r.rlim_max = r.rlim_cur = (rlim_t) wp->config->rlimit_files;

		if (0 > setrlimit(RLIMIT_NOFILE, &r)) {
			zlog(ZLOG_SYSERROR, "[pool %s] failed to set rlimit_files for this pool. Please check your system limits or decrease rlimit_files. setrlimit(RLIMIT_NOFILE, %d)", wp->config->name, wp->config->rlimit_files);
		}
	}

	if (wp->config->rlimit_core) {
		struct rlimit r;

		r.rlim_max = r.rlim_cur = wp->config->rlimit_core == -1 ? (rlim_t) RLIM_INFINITY : (rlim_t) wp->config->rlimit_core;

		if (0 > setrlimit(RLIMIT_CORE, &r)) {
			zlog(ZLOG_SYSERROR, "[pool %s] failed to set rlimit_core for this pool. Please check your system limits or decrease rlimit_core. setrlimit(RLIMIT_CORE, %d)", wp->config->name, wp->config->rlimit_core);
		}
	}

	if (is_root && wp->config->chroot && *wp->config->chroot) {
		if (0 > chroot(wp->config->chroot)) {
			zlog(ZLOG_SYSERROR, "[pool %s] failed to chroot(%s)",  wp->config->name, wp->config->chroot);
			return -1;
		}
		made_chroot = 1;
	}

	if (wp->config->chdir && *wp->config->chdir) {
		if (0 > chdir(wp->config->chdir)) {
			zlog(ZLOG_SYSERROR, "[pool %s] failed to chdir(%s)", wp->config->name, wp->config->chdir);
			return -1;
		}
	} else if (made_chroot) {
		chdir("/");
	}

	if (is_root) {

		if (wp->config->process_priority != 64) {
			if (setpriority(PRIO_PROCESS, 0, wp->config->process_priority) < 0) {
				zlog(ZLOG_SYSERROR, "[pool %s] Unable to set priority for this new process", wp->config->name);
				return -1;
			}
		}

		if (wp->set_gid) {
			if (0 > setgid(wp->set_gid)) {
				zlog(ZLOG_SYSERROR, "[pool %s] failed to setgid(%d)", wp->config->name, wp->set_gid);
				return -1;
			}
		}
		if (wp->set_uid) {
			if (0 > initgroups(wp->config->user, wp->set_gid)) {
				zlog(ZLOG_SYSERROR, "[pool %s] failed to initgroups(%s, %d)", wp->config->name, wp->config->user, wp->set_gid);
				return -1;
			}
			if (0 > setuid(wp->set_uid)) {
				zlog(ZLOG_SYSERROR, "[pool %s] failed to setuid(%d)", wp->config->name, wp->set_uid);
				return -1;
			}
		}
	}

#ifdef HAVE_PRCTL
	if (0 > prctl(PR_SET_DUMPABLE, 1, 0, 0, 0)) {
		zlog(ZLOG_SYSERROR, "[pool %s] failed to prctl(PR_SET_DUMPABLE)", wp->config->name);
	}
#endif

	if (0 > fpm_clock_init()) {
		return -1;
	}
	return 0;
}
コード例 #29
0
ファイル: ImageLoaderQueue.cpp プロジェクト: Lingrui/TS
void *FileLoader ( void *arg )
{
  ImageLoadWorkInfo *master_img_loader = ( ImageLoadWorkInfo * ) arg;

  prctl(PR_SET_NAME,"FileLoader",0,0,0);


  WorkerInfoQueue *loadWorkQ = new WorkerInfoQueue ( master_img_loader->flow_buffer_size );


  ImageLoadWorkInfo *n_image_loaders = new ImageLoadWorkInfo[master_img_loader->flow_buffer_size];
  SetUpIndividualImageLoaders ( n_image_loaders,master_img_loader );


  //   int numWorkers = 1;
  int numWorkers = numCores() /4; // @TODO - this should be subject to inception_state options
  numWorkers = ( numWorkers < 4 ? 4:numWorkers );
  fprintf ( stdout, "FileLoader: numWorkers threads = %d\n", numWorkers );
  WqInfo_t wq_info[numWorkers];

  {
    int cworker;
    pthread_t work_thread;
    // spawn threads for doing background correction/fitting work
    for ( cworker = 0; cworker < numWorkers; cworker++ )
    {
      wq_info[cworker].threadNum=cworker;
      wq_info[cworker].wq = loadWorkQ;
      int t = pthread_create ( &work_thread, NULL, FileLoadWorker,
                               &wq_info[cworker] );
      pthread_detach(work_thread);
      if ( t )
        fprintf ( stderr, "Error starting thread\n" );
    }
  }

  WorkerInfoQueueItem item;

  //time_t start, end;
  int flow_buffer_size = master_img_loader->flow_buffer_size;

  // this loop goes over the individual image loaders
  for ( int i_buffer = 0; i_buffer < flow_buffer_size; i_buffer++ )
  {
    ImageLoadWorkInfo *cur_image_loader = &n_image_loaders[i_buffer];

    int cur_flow = cur_image_loader->flow;  // each job is an n_image_loaders item

    DontReadAheadOfSignalProcessing (cur_image_loader, master_img_loader->lead);
    //***We are doing this on this thread so we >load< in sequential order that pinned in Flow updates in sequential order
    if (!cur_image_loader->inception_state->img_control.threaded_file_access) {
      JustLoadOneImageWithPinnedUpdate(cur_image_loader);
    }
    //*** now we can do the rest of the computation for an image, including dumping in a multiply threaded fashion

    item.finished = false;
    item.private_data = cur_image_loader;
    loadWorkQ->PutItem ( item );

    if (!ChipIdDecoder::IsProtonChip())
      PauseForLongCompute ( cur_flow,cur_image_loader );
  }

  // wait for all of the images to be processed
  loadWorkQ->WaitTillDone();
  KillQueue ( loadWorkQ,numWorkers );

  delete loadWorkQ;
  delete[] n_image_loaders;

  master_img_loader->finished = true;

  return NULL;
}
コード例 #30
0
void *auth_mgr_adns_handler_epoll(void *arg)
{
    //struct timeval *tvp, tv, tv_copy;
    ares_socket_t dns_client_fds[16] = {0};
    struct epoll_event ev, events[DNS_MAX_EVENTS];
    int i,bitmask,nfds, epollfd, timeout, fd_count, ret;

    UNUSED_ARGUMENT(arg);
    memset(dns_client_fds, 0, sizeof(dns_client_fds));

    memset((char *)&ev, 0, sizeof(struct epoll_event));
    memset((char *)&events[0], 0, sizeof(events));

    epollfd = epoll_create(DNS_MAX_SERVERS);
    if (epollfd < 0) {
        DBG_LOG(SEVERE, MOD_AUTHMGR, "epoll_create() error");
        assert(0);
    }

    prctl(PR_SET_NAME, "nvsd-adns", 0, 0, 0);

    /*Infinite loop, to process all the dns responses. Each channel can handle
     16 name servers in RR fashion. Inside each channel there is one socket
    dedicated for one nameserver. So if there are 2 nameservers in /etc/resol.conf
    , then c-ares will assign 2 fds to the channel*/
    while(1)
    {
        nfds=0;
        bitmask=0;
        for (i =0; i < DNS_MAX_SERVERS ; i++) {
            if (dns_client_fds[i] > 0) {
                if (epoll_ctl(epollfd, EPOLL_CTL_DEL, dns_client_fds[i], NULL) < 0) {
                    //not a serious problem, strange that we should hit this case
                    continue;
                }
            }
        }
        memset(dns_client_fds, 0, sizeof(dns_client_fds));
        pthread_mutex_lock(&cares_mutex);
        bitmask = ares_getsock(channel, dns_client_fds, DNS_MAX_SERVERS);
        for (i =0; i < DNS_MAX_SERVERS ; i++) {
            if (dns_client_fds[i] > 0) {
                ev.events = 0;
                if (ARES_GETSOCK_READABLE(bitmask, i)) {
                    ev.events |= EPOLLIN;
                }
                if (ARES_GETSOCK_WRITABLE(bitmask, i)) {
                    ev.events |= EPOLLOUT;
                }
                ev.data.fd = dns_client_fds[i];
                if (epoll_ctl(epollfd, EPOLL_CTL_ADD, dns_client_fds[i], &ev) < 0) {
                    if(errno == EEXIST) {
                        nfds++;
                        continue;
                    }
                    DBG_LOG(SEVERE, MOD_AUTHMGR, "%d fd has trouble when adding to epoll:%s\n",
                            dns_client_fds[i], strerror(errno));
                    continue;
                }
                nfds++;
            }
        }
        if(nfds==0)
        {
            pthread_cond_wait(&cares_cond, &cares_mutex);
            pthread_mutex_unlock(&cares_mutex);
            continue;
        }
        //tvp = ares_timeout(channel, NULL, &tv);
        //memcpy(&tv_copy, tvp, sizeof(struct timeval));
        pthread_mutex_unlock(&cares_mutex);
        //timeout = (tv_copy.tv_sec)*1000;//millisecs
        timeout = 1000;//millisecs
        /*********************************************************
        The default timeout was 5 seconds with default retries
        as 4. The timeout algorith that c-ares adopts, has
        timeout increasing linearly for every retry, and can
        go upto 75secs(~5+~10+~20+~40). To avoid such a big
        block in our select, reduced the timeout to 3secs
        and retries to 2, so max blocking limited to 9 secs
        Changes in ares_init.
        ******************************************************/
        fd_count = epoll_wait(epollfd, events, DNS_MAX_EVENTS, timeout);
        if (fd_count < 0) {
            DBG_LOG(SEVERE, MOD_AUTHMGR, "epoll_wait failed:%s", strerror(errno));
            continue;
        }
        pthread_mutex_lock(&cares_mutex);
        if (fd_count > 0) {
            for (i = 0; i < fd_count; ++i) {
                ares_process_fd(channel,
                                ((events[i].events) & (EPOLLIN) ?
                                 events[i].data.fd:ARES_SOCKET_BAD),
                                ((events[i].events) & (EPOLLOUT)?
                                 events[i].data.fd:ARES_SOCKET_BAD));
            }
        } else {
            ares_process_fd(channel, ARES_SOCKET_BAD, ARES_SOCKET_BAD);
        }
        if (channel_ready == 0 ) {
            ares_destroy(channel);
            //re-init the channel to get a new port
            ret = ares_init_options(&channel, &options, optmask);
            if (ret != ARES_SUCCESS) {
                DBG_LOG(SEVERE, MOD_AUTHMGR,"ares_init: %d %s", ret, ares_strerror(ret));
                assert(0);
            }
            channel_ready = 1;
            AO_fetch_and_add1(&glob_dns_channel_reinit);
        }
        pthread_mutex_unlock(&cares_mutex);
    }
}