Skip to content

Commit bb61a06

Browse files
authored
APP-7128 support modules on windows (#4605)
1 parent bb66c37 commit bb61a06

File tree

8 files changed

+333
-248
lines changed

8 files changed

+333
-248
lines changed

Makefile

+2-1
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,8 @@ full-static:
8383

8484
windows:
8585
mkdir -p bin/windows
86-
GOOS=windows go build -tags no_cgo -ldflags="-extldflags=-static $(COMMON_LDFLAGS)" -o bin/windows/viam-server-$(shell go env GOARCH) ./web/cmd/server
86+
GOOS=windows go build -tags no_cgo -ldflags="-extldflags=-static $(COMMON_LDFLAGS)" -o bin/windows/viam-server-$(shell go env GOARCH).exe ./web/cmd/server
87+
cd bin/windows && zip viam.zip viam-server-$(shell go env GOARCH).exe
8788

8889
server-static-compressed: server-static
8990
upx --best --lzma $(BIN_OUTPUT_PATH)/viam-server

ftdc/ftdc.go

+9
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"path"
1111
"path/filepath"
1212
"regexp"
13+
"runtime"
1314
"slices"
1415
"strconv"
1516
"strings"
@@ -207,6 +208,11 @@ func (ftdc *FTDC) Remove(name string) {
207208
// Start spins off the background goroutine for collecting + writing FTDC data. It's normal for tests
208209
// to _not_ call `Start`. Tests can simulate the same functionality by calling `constructDatum` and `writeDatum`.
209210
func (ftdc *FTDC) Start() {
211+
if runtime.GOOS == "windows" {
212+
// note: this logs a panic on RDK start on windows.
213+
ftdc.logger.Warn("FTDC not implemented on windows, not starting")
214+
return
215+
}
210216
ftdc.readStatsWorker = utils.NewStoppableWorkerWithTicker(time.Second, ftdc.statsReader)
211217
utils.PanicCapturingGo(ftdc.statsWriter)
212218

@@ -276,6 +282,9 @@ func (ftdc *FTDC) statsWriter() {
276282
// `statsWriter` by hand, without the `statsReader` can `close(ftdc.datumCh)` followed by
277283
// `<-ftdc.outputWorkerDone` to stop+wait for the `statsWriter`.
278284
func (ftdc *FTDC) StopAndJoin(ctx context.Context) {
285+
if runtime.GOOS == "windows" {
286+
return
287+
}
279288
ftdc.stopOnce.Do(func() {
280289
// Only one caller should close the datum channel. And it should be the caller that called
281290
// stop on the worker writing to the channel.

module/modmanager/manager.go

+37-16
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"os"
99
"path/filepath"
1010
"slices"
11+
"strconv"
1112
"strings"
1213
"sync"
1314
"sync/atomic"
@@ -42,6 +43,9 @@ import (
4243
rutils "go.viam.com/rdk/utils"
4344
)
4445

46+
// tcpPortRange is the beginning of the port range. Only used when ViamTCPSockets() = true.
47+
const tcpPortRange = 13500
48+
4549
var (
4650
validateConfigTimeout = 5 * time.Second
4751
errMessageExitStatus143 = "exit status 143"
@@ -70,6 +74,7 @@ func NewManager(
7074
restartCtxCancel: restartCtxCancel,
7175
packagesDir: options.PackagesDir,
7276
ftdc: options.FTDC,
77+
nextPort: tcpPortRange,
7378
}
7479
}
7580

@@ -102,8 +107,9 @@ type module struct {
102107
inStartup atomic.Bool
103108
inRecoveryLock sync.Mutex
104109
logger logging.Logger
105-
106-
ftdc *ftdc.FTDC
110+
ftdc *ftdc.FTDC
111+
// port stores the listen port of this module when ViamTCPSockets() = true.
112+
port int
107113
}
108114

109115
type addedResource struct {
@@ -183,8 +189,9 @@ type Manager struct {
183189
removeOrphanedResources func(ctx context.Context, rNames []resource.Name)
184190
restartCtx context.Context
185191
restartCtxCancel context.CancelFunc
186-
187-
ftdc *ftdc.FTDC
192+
ftdc *ftdc.FTDC
193+
// nextPort manages ports when ViamTCPSockets() = true.
194+
nextPort int
188195
}
189196

190197
// Close terminates module connections and processes.
@@ -326,7 +333,9 @@ func (mgr *Manager) add(ctx context.Context, conf config.Module, moduleLogger lo
326333
resources: map[resource.Name]*addedResource{},
327334
logger: moduleLogger,
328335
ftdc: mgr.ftdc,
336+
port: mgr.nextPort,
329337
}
338+
mgr.nextPort++
330339

331340
if err := mgr.startModule(ctx, mod); err != nil {
332341
return err
@@ -996,8 +1005,12 @@ func (mgr *Manager) attemptRestart(ctx context.Context, mod *module) []resource.
9961005
func (m *module) dial() error {
9971006
// TODO(PRODUCT-343): session support probably means interceptors here
9981007
var err error
1008+
addrToDial := m.addr
1009+
if !rutils.TCPRegex.MatchString(addrToDial) {
1010+
addrToDial = "unix://" + m.addr
1011+
}
9991012
conn, err := grpc.Dial( //nolint:staticcheck
1000-
"unix://"+m.addr,
1013+
addrToDial,
10011014
grpc.WithTransportCredentials(insecure.NewCredentials()),
10021015
grpc.WithChainUnaryInterceptor(
10031016
rdkgrpc.EnsureTimeoutUnaryClientInterceptor,
@@ -1104,11 +1117,16 @@ func (m *module) startProcess(
11041117
packagesDir string,
11051118
) error {
11061119
var err error
1107-
// append a random alpha string to the module name while creating a socket address to avoid conflicts
1108-
// with old versions of the module.
1109-
if m.addr, err = modlib.CreateSocketAddress(
1110-
filepath.Dir(parentAddr), fmt.Sprintf("%s-%s", m.cfg.Name, utils.RandomAlphaString(5))); err != nil {
1111-
return err
1120+
1121+
if rutils.ViamTCPSockets() {
1122+
m.addr = "127.0.0.1:" + strconv.Itoa(m.port)
1123+
} else {
1124+
// append a random alpha string to the module name while creating a socket address to avoid conflicts
1125+
// with old versions of the module.
1126+
if m.addr, err = modlib.CreateSocketAddress(
1127+
filepath.Dir(parentAddr), fmt.Sprintf("%s-%s", m.cfg.Name, utils.RandomAlphaString(5))); err != nil {
1128+
return err
1129+
}
11121130
}
11131131

11141132
// We evaluate the Module's ExePath absolutely in the viam-server process so that
@@ -1176,12 +1194,15 @@ func (m *module) startProcess(
11761194
)
11771195
}
11781196
}
1179-
err = modlib.CheckSocketOwner(m.addr)
1180-
if errors.Is(err, fs.ErrNotExist) {
1181-
continue
1182-
}
1183-
if err != nil {
1184-
return errors.WithMessage(err, "module startup failed")
1197+
if !rutils.TCPRegex.MatchString(m.addr) {
1198+
// note: we don't do this check in TCP mode because TCP addresses are not file paths and will fail check.
1199+
err = modlib.CheckSocketOwner(m.addr)
1200+
if errors.Is(err, fs.ErrNotExist) {
1201+
continue
1202+
}
1203+
if err != nil {
1204+
return errors.WithMessage(err, "module startup failed")
1205+
}
11851206
}
11861207
break
11871208
}

0 commit comments

Comments
 (0)