| 99 | } |
| 100 | |
| 101 | func newWorker(o workerOpt) (*worker, error) { |
| 102 | // Order is important! |
| 103 | // This order ensures that FrankenPHP started from inside a symlinked directory will properly resolve any paths. |
| 104 | // If it is started from outside a symlinked directory, it is resolved to the same path that we use in the Caddy module. |
| 105 | absFileName, err := filepath.EvalSymlinks(filepath.FromSlash(o.fileName)) |
| 106 | if err != nil { |
| 107 | return nil, fmt.Errorf("worker filename is invalid %q: %w", o.fileName, err) |
| 108 | } |
| 109 | |
| 110 | absFileName, err = fastabs.FastAbs(absFileName) |
| 111 | if err != nil { |
| 112 | return nil, fmt.Errorf("worker filename is invalid %q: %w", o.fileName, err) |
| 113 | } |
| 114 | |
| 115 | if _, err := os.Stat(absFileName); err != nil { |
| 116 | return nil, fmt.Errorf("worker file not found %q: %w", absFileName, err) |
| 117 | } |
| 118 | |
| 119 | if o.name == "" { |
| 120 | o.name = absFileName |
| 121 | } |
| 122 | |
| 123 | // workers that have a name starting with "m#" are module workers |
| 124 | // they can only be matched by their name, not by their path |
| 125 | allowPathMatching := !strings.HasPrefix(o.name, "m#") |
| 126 | |
| 127 | if w := workersByPath[absFileName]; w != nil && allowPathMatching { |
| 128 | return w, fmt.Errorf("two workers cannot have the same filename: %q", absFileName) |
| 129 | } |
| 130 | if w := workersByName[o.name]; w != nil { |
| 131 | return w, fmt.Errorf("two workers cannot have the same name: %q", o.name) |
| 132 | } |
| 133 | |
| 134 | if o.env == nil { |
| 135 | o.env = make(PreparedEnv, 1) |
| 136 | } |
| 137 | |
| 138 | o.env["FRANKENPHP_WORKER\x00"] = "1" |
| 139 | w := &worker{ |
| 140 | name: o.name, |
| 141 | fileName: absFileName, |
| 142 | requestOptions: o.requestOptions, |
| 143 | num: o.num, |
| 144 | maxThreads: o.maxThreads, |
| 145 | requestChan: make(chan contextHolder), |
| 146 | threads: make([]*phpThread, 0, o.num), |
| 147 | allowPathMatching: allowPathMatching, |
| 148 | maxConsecutiveFailures: o.maxConsecutiveFailures, |
| 149 | onThreadReady: o.onThreadReady, |
| 150 | onThreadShutdown: o.onThreadShutdown, |
| 151 | } |
| 152 | |
| 153 | w.configureMercure(&o) |
| 154 | |
| 155 | w.requestOptions = append( |
| 156 | w.requestOptions, |
| 157 | WithRequestDocumentRoot(filepath.Dir(o.fileName), false), |
| 158 | WithRequestPreparedEnv(o.env), |